Files
mercury/compiler/rbmm.condition_renaming.m
2022-11-18 20:23:11 +11:00

1183 lines
50 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 2007-2008, 2010-2012 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.condition_renaming.m.
% Main author: Quan Phan.
%
% The region analysis may introduce creations for region variables
% which are non-local to an if-then-else in the condition goal of the
% if-then-else.
% This module finds which renaming and reverse renaming are needed at each
% program point so that the binding of non-local regions in the condition
% goal of an if-then-else is resolved.
%
% When reasoning about the renaming and reverse renaming needed for
% an if-then-else here we take into account the changes to regions caused
% by the renaming and renaming annotations needed for region resurrection.
% This can be viewed as if the program is transformed by the renaming
% and reverse renaming for region resurrection first. This is to solve the
% problem with region resurrection. Then that transformed program is
% transformed again to solve the problem with if-then-else. Note that the
% first transformation may add to the problem with if-then-else, e.g.,
% when it introduces reverse renaming to a non-local variable inside the
% condition goal of an if-then-else.
%
% XXX This approach is fundamentally misconceived. The right approach would be
% for the analysis up to this point to work with identifiers representing
% regions, and for another pass to map each region to one or more program
% variables. This naturally allows N different lifetimes of a region inside a
% procedure to be represented by N different program variables.
%
%---------------------------------------------------------------------------%
:- module transform_hlds.rbmm.condition_renaming.
:- interface.
:- import_module hlds.
:- import_module hlds.hlds_module.
:- import_module hlds.hlds_pred.
:- import_module mdbcomp.
:- import_module mdbcomp.goal_path.
:- import_module transform_hlds.rbmm.points_to_info.
:- import_module transform_hlds.rbmm.region_liveness_info.
:- import_module transform_hlds.rbmm.region_resurrection_renaming.
:- import_module map.
:- import_module set.
%---------------------------------------------------------------------------%
:- type proc_goal_path_regions_table ==
map(pred_proc_id, goal_path_regions_table).
:- type goal_path_regions_table == map(reverse_goal_path, set(string)).
% XXX The key type should be goal_id.
% This predicate collects two pieces of information.
%
% 1. The non-local regions of if-then-elses.
% A region is non-local to an if-then-else if the region is created
% in the if-then-else and outlives the scope of the if-then-else.
% 2. The regions which are created (get bound) in the condition
% goals of if-then-else.
%
% We will only store information about a procedure if the information
% exists. That means, for example, there is no entry which maps a PPId
% to empty.
%
% This information is used to compute the regions which need to be renamed,
% i.e., both non-local and created in the condition of an if-then-else.
%
:- pred collect_non_local_and_in_cond_regions(module_info::in,
rpta_info_table::in, proc_pp_region_set_table::in,
proc_pp_region_set_table::in, rbmm_renaming_table::in,
rbmm_renaming_annotation_table::in, proc_goal_path_regions_table::out,
proc_goal_path_regions_table::out) is det.
% After having the 2 pieces of information calculated above, this step
% is simple. The only thing to note here is that we will only store
% information for a procedure when the information exists.
% This means that a procedure in which no renaming is required will not
% be in the resulting table.
%
:- pred collect_ite_renamed_regions(proc_goal_path_regions_table::in,
proc_goal_path_regions_table::in, proc_goal_path_regions_table::out)
is det.
% This predicate ONLY traverses the procedures which requires
% condition renaming and for each condition goal in such a procedure
% it introduces the necessary renamings.
% The renaming information is stored in the form:
% a program point (in the condition goal) --> necessary renaming at
% the point.
% A new name for a region (variable) at a program point is:
% RegionName_ite_Number, where Number is the number of condition goals
% to which the program point belongs.
%
:- pred collect_ite_renaming(module_info::in, rpta_info_table::in,
proc_goal_path_regions_table::in, rbmm_renaming_table::out) is det.
% In the then branch of an if-then-else in which renaming happens we
% need to introduce reverse renaming annotation in the form of
% assignments, e.g., if R is renamed to R_ite_1 in the condition
% then we add R = R_ite_1 in the then branch.
% Because the if-then-else can lie inside the condition goals of
% other if-then-elses, we need to apply the renaming at the
% program point where the annotation is attached.
% E.g., At the point renaming R --> R_ite_2 exists, then the
% added annotation is R_ite_2 = R_ite_1.
%
% This predicate will also traverse only procedures in which renaming
% 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 point.
% 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,
rbmm_renaming_table::in, rbmm_renaming_table::out,
rbmm_renaming_annotation_table::out) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module hlds.goal_form.
:- import_module hlds.goal_path.
:- import_module hlds.hlds_goal.
:- import_module transform_hlds.rbmm.points_to_graph.
:- import_module transform_hlds.rbmm.region_instruction.
:- import_module transform_hlds.smm_common.
:- import_module int.
:- import_module list.
:- import_module pair.
:- import_module require.
:- import_module string.
%---------------------------------------------------------------------------%
collect_non_local_and_in_cond_regions(ModuleInfo, RptaInfoTable,
LRBeforeTable, LRAfterTable, ResurRenamingTable,
ResurRenamingAnnoTable, NonLocalRegionsTable, InCondRegionsTable) :-
module_info_get_valid_pred_ids(ModuleInfo, PredIds),
list.foldl2(collect_non_local_and_in_cond_regions_pred(ModuleInfo,
RptaInfoTable, LRBeforeTable, LRAfterTable, ResurRenamingTable,
ResurRenamingAnnoTable), PredIds,
map.init, NonLocalRegionsTable, map.init, InCondRegionsTable).
:- pred collect_non_local_and_in_cond_regions_pred(module_info::in,
rpta_info_table::in, proc_pp_region_set_table::in,
proc_pp_region_set_table::in, rbmm_renaming_table::in,
rbmm_renaming_annotation_table::in, pred_id::in,
proc_goal_path_regions_table::in, proc_goal_path_regions_table::out,
proc_goal_path_regions_table::in, proc_goal_path_regions_table::out)
is det.
collect_non_local_and_in_cond_regions_pred(ModuleInfo, RptaInfoTable,
LRBeforeTable, LRAfterTable, ResurRenamingTable,
ResurRenamingAnnoTable, PredId, !NonLocalRegionsTable,
!InCondRegionsTable) :-
module_info_pred_info(ModuleInfo, PredId, PredInfo),
ProcIds = pred_info_valid_non_imported_procids(PredInfo),
list.foldl2(collect_non_local_and_in_cond_regions_proc(ModuleInfo,
PredId, RptaInfoTable, LRBeforeTable, LRAfterTable,
ResurRenamingTable, ResurRenamingAnnoTable), ProcIds,
!NonLocalRegionsTable, !InCondRegionsTable).
:- pred collect_non_local_and_in_cond_regions_proc(module_info::in,
pred_id::in, rpta_info_table::in, proc_pp_region_set_table::in,
proc_pp_region_set_table::in, rbmm_renaming_table::in,
rbmm_renaming_annotation_table::in, proc_id::in,
proc_goal_path_regions_table::in, proc_goal_path_regions_table::out,
proc_goal_path_regions_table::in, proc_goal_path_regions_table::out)
is det.
collect_non_local_and_in_cond_regions_proc(ModuleInfo, PredId,
RptaInfoTable, LRBeforeTable, LRAfterTable, ResurRenamingTable,
ResurRenamingAnnoTable, ProcId,
!NonLocalRegionsTable, !InCondRegionsTable) :-
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_in_proc(ModuleInfo, ProcInfo0, ProcInfo),
proc_info_get_goal(ProcInfo, Goal),
map.lookup(RptaInfoTable, PPId, rpta_info(Graph, _)),
map.lookup(LRBeforeTable, PPId, LRBeforeProc),
map.lookup(LRAfterTable, PPId, LRAfterProc),
( if map.search(ResurRenamingTable, PPId, ResurRenamingProc0) then
ResurRenamingProc = ResurRenamingProc0
else
ResurRenamingProc = map.init
),
( if
map.search(ResurRenamingAnnoTable, PPId, ResurRenamingAnnoProc0)
then
ResurRenamingAnnoProc = ResurRenamingAnnoProc0
else
ResurRenamingAnnoProc = map.init
),
collect_non_local_and_in_cond_regions_goal(Graph,
LRBeforeProc, LRAfterProc, ResurRenamingProc,
ResurRenamingAnnoProc, Goal,
map.init, NonLocalRegionsProc,
map.init, InCondRegionsProc),
( if map.count(NonLocalRegionsProc) = 0 then
true
else
map.set(PPId, NonLocalRegionsProc, !NonLocalRegionsTable)
),
( if map.count(InCondRegionsProc) = 0 then
true
else
map.set(PPId, InCondRegionsProc, !InCondRegionsTable)
)
).
:- pred collect_non_local_and_in_cond_regions_goal(rpt_graph::in,
pp_region_set_table::in, pp_region_set_table::in,
rbmm_renaming_proc::in, rbmm_renaming_annotation_proc::in, hlds_goal::in,
goal_path_regions_table::in, goal_path_regions_table::out,
goal_path_regions_table::in, goal_path_regions_table::out) is det.
collect_non_local_and_in_cond_regions_goal(Graph, LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc, Goal,
!NonLocalRegionsProc, !InCondRegionsProc) :-
Goal = hlds_goal(Expr, _),
collect_non_local_and_in_cond_regions_expr(Graph, LRBeforeProc,
LRAfterProc, ResurRenamingProc, ResurRenamingAnnoProc, Expr,
!NonLocalRegionsProc, !InCondRegionsProc).
:- pred collect_non_local_and_in_cond_regions_expr(rpt_graph::in,
pp_region_set_table::in, pp_region_set_table::in,
rbmm_renaming_proc::in, rbmm_renaming_annotation_proc::in,
hlds_goal_expr::in,
goal_path_regions_table::in, goal_path_regions_table::out,
goal_path_regions_table::in, goal_path_regions_table::out) is det.
collect_non_local_and_in_cond_regions_expr(Graph, LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc, conj(_, Conjs),
!NonLocalRegionsProc, !InCondRegionsProc) :-
list.foldl2(
collect_non_local_and_in_cond_regions_goal(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc),
Conjs, !NonLocalRegionsProc, !InCondRegionsProc).
collect_non_local_and_in_cond_regions_expr(_, _, _, _, _,
plain_call(_, _, _, _, _, _),
!NonLocalRegionsProc, !InCondRegionsProc).
collect_non_local_and_in_cond_regions_expr(_, _, _, _, _,
generic_call(_, _, _, _, _),
!NonLocalRegionsProc, !InCondRegionsProc).
collect_non_local_and_in_cond_regions_expr(_, _, _, _, _,
call_foreign_proc(_, _, _, _, _, _, _),
!NonLocalRegionsProc, !InCondRegionsProc).
collect_non_local_and_in_cond_regions_expr(Graph, LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc, switch(_, _, Cases),
!NonLocalRegionsProc, !InCondRegionsProc) :-
list.foldl2(
collect_non_local_and_in_cond_regions_case(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc),
Cases, !NonLocalRegionsProc, !InCondRegionsProc).
collect_non_local_and_in_cond_regions_expr(Graph, LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc, disj(Disjs),
!NonLocalRegionsProc, !InCondRegionsProc) :-
list.foldl2(
collect_non_local_and_in_cond_regions_goal(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc),
Disjs, !NonLocalRegionsProc, !InCondRegionsProc).
collect_non_local_and_in_cond_regions_expr(Graph, LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc, negation(Goal),
!NonLocalRegionsProc, !InCondRegionsProc) :-
collect_non_local_and_in_cond_regions_goal(Graph, LRBeforeProc,
LRAfterProc, ResurRenamingProc, ResurRenamingAnnoProc, Goal,
!NonLocalRegionsProc, !InCondRegionsProc).
collect_non_local_and_in_cond_regions_expr(_, _, _, _, _,
unify(_, _, _, _, _), !NonLocalRegionsProc, !InCondRegionsProc).
collect_non_local_and_in_cond_regions_expr(Graph, LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc, scope(_, Goal),
!NonLocalRegionsProc, !InCondRegionsProc) :-
% XXX We should special-case the handling of from_ground_term_construct
% scopes.
collect_non_local_and_in_cond_regions_goal(Graph, LRBeforeProc,
LRAfterProc, ResurRenamingProc, ResurRenamingAnnoProc, Goal,
!NonLocalRegionsProc, !InCondRegionsProc).
collect_non_local_and_in_cond_regions_expr(Graph, LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc, Expr,
!NonLocalRegionProc, !InCondRegionsProc) :-
Expr = if_then_else(_, Cond, Then, Else),
% We only care about regions created inside condition goals.
collect_regions_created_in_condition(Graph, LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc, Cond, !InCondRegionsProc),
% The sets of non_local regions in the (Cond, Then) and in the (Else)
% branch are the same, therefore we will only calculate in one of them.
% As it is here, we calculate for (Else) with the hope that it is
% usually more efficient (only Else compared to both Cond and Then).
collect_non_local_and_in_cond_regions_goal(Graph,
LRBeforeProc, LRAfterProc, ResurRenamingProc, ResurRenamingAnnoProc,
Cond, !NonLocalRegionProc, !InCondRegionsProc),
collect_non_local_and_in_cond_regions_goal(Graph,
LRBeforeProc, LRAfterProc, ResurRenamingProc, ResurRenamingAnnoProc,
Then, !NonLocalRegionProc, !InCondRegionsProc),
collect_non_local_regions_in_ite(Graph,
LRBeforeProc, LRAfterProc, ResurRenamingProc, ResurRenamingAnnoProc,
Else, !NonLocalRegionProc).
collect_non_local_and_in_cond_regions_expr(_, _, _, _, _, shorthand(_),
!NonLocalRegionProc, !InCondRegionsProc) :-
% These should have been expanded out by now.
unexpected($pred, "shorthand").
:- pred collect_non_local_and_in_cond_regions_case(rpt_graph::in,
pp_region_set_table::in, pp_region_set_table::in,
rbmm_renaming_proc::in, rbmm_renaming_annotation_proc::in, case::in,
goal_path_regions_table::in, goal_path_regions_table::out,
goal_path_regions_table::in, goal_path_regions_table::out) is det.
collect_non_local_and_in_cond_regions_case(Graph, LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc, Case,
!NonLocalRegionProc, !InCondRegionsProc) :-
Case = case(_, _, Goal),
collect_non_local_and_in_cond_regions_goal(Graph,
LRBeforeProc, LRAfterProc, ResurRenamingProc, ResurRenamingAnnoProc,
Goal, !NonLocalRegionProc, !InCondRegionsProc).
:- pred collect_non_local_regions_in_ite(rpt_graph::in,
pp_region_set_table::in, pp_region_set_table::in, rbmm_renaming_proc::in,
rbmm_renaming_annotation_proc::in, hlds_goal::in,
goal_path_regions_table::in, goal_path_regions_table::out) is det.
collect_non_local_regions_in_ite(Graph, LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc, GoalInIte,
!NonLocalRegionProc) :-
GoalInIte = hlds_goal(Expr, Info),
HasSubGoals = goal_expr_has_subgoals(Expr),
(
HasSubGoals = does_not_have_subgoals,
ProgPoint = program_point_init(Info),
ProgPoint = pp(_, RevGoalPath),
map.lookup(LRBeforeProc, ProgPoint, LRBefore),
map.lookup(LRAfterProc, ProgPoint, LRAfter),
% XXX We may also need VoidVarRegionTable to be
% included in RemovedAfter.
set.difference(LRBefore, LRAfter, RemovedAfterNodes),
set.difference(LRAfter, LRBefore, CreatedBeforeNodes),
% Those sets need to subject to resurrection renaming
% and annotations.
% Apply resurrection renaming to those sets.
% For each renaming annotation, the left one is put into CreatedBefore,
% and the right one is put into RemovedAfter.
( if map.search(ResurRenamingProc, ProgPoint, ResurRenaming0) then
ResurRenaming = ResurRenaming0
else
ResurRenaming = map.init
),
set.fold(apply_region_renaming(Graph, ResurRenaming),
RemovedAfterNodes, set.init, RemovedAfterRegions0),
set.fold(apply_region_renaming(Graph, ResurRenaming),
CreatedBeforeNodes, set.init, CreatedBeforeRegions0),
( if
map.search(ResurRenamingAnnoProc, ProgPoint, ResurRenamingAnnos0)
then
ResurRenamingAnnos = ResurRenamingAnnos0
else
ResurRenamingAnnos = []
),
list.foldl2(renaming_annotation_to_regions,
ResurRenamingAnnos, set.init, LeftRegions, set.init, RightRegions),
set.union(RemovedAfterRegions0, RightRegions, RemovedAfterRegions),
set.union(CreatedBeforeRegions0, LeftRegions, CreatedBeforeRegions),
record_non_local_regions(RevGoalPath, CreatedBeforeRegions,
RemovedAfterRegions, !NonLocalRegionProc)
;
HasSubGoals = has_subgoals,
collect_non_local_regions_in_ite_compound_goal(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc,
GoalInIte, !NonLocalRegionProc)
).
:- pred apply_region_renaming(rpt_graph::in, rbmm_renaming::in, rptg_node::in,
set(string)::in, set(string)::out) is det.
apply_region_renaming(Graph, Renaming, Node, !Regions) :-
RegionName = rptg_lookup_region_name(Graph, Node),
( if map.search(Renaming, RegionName, RenamedRegionNameList) then
RenamedRegionName = list.det_last(RenamedRegionNameList),
set.insert(RenamedRegionName, !Regions)
else
set.insert(RegionName, !Regions)
).
:- pred renaming_annotation_to_regions(region_instr::in,
set(string)::in, set(string)::out,
set(string)::in, set(string)::out) is det.
renaming_annotation_to_regions(RenameAnnotation, !LeftRegions,
!RightRegions) :-
(
( RenameAnnotation = create_region(_)
; RenameAnnotation = remove_region(_)
),
unexpected($pred, "annotation is not assignment")
;
RenameAnnotation = rename_region(RightRegion, LeftRegion),
set.insert(LeftRegion, !LeftRegions),
set.insert(RightRegion, !RightRegions)
).
% The non-local regions of an if-then-else will be attached to
% the goal path to the condition.
% Non-local regions of an if-then-else are ones that are created
% somewhere inside the if-then-else and not be removed inside it
% (i.e., outlive the if-then-else's scope).
% If a region is created in an if-then-else, it is created
% in both (Cond, Then) and (Else) branches. (Of cource one of them
% is in effect at runtime). If it is removed in the if-then-else
% then it is also removed in both. Therefore it is enough to
% consider either (Cond, Then) or (Else). As said above,
% we here choose to calculate for (Else).
%
% The algorithm is that: at each program point (inside the else),
% the non-local set of regions is updated by including the regions
% created before or at that program point and excluding those removed
% at or after the program point.
% Because if-then-else can be nested, we need to update the
% non-local sets of all the surrounding if-then-elses of this
% program point.
%
:- pred record_non_local_regions(reverse_goal_path::in, set(string)::in,
set(string)::in,
goal_path_regions_table::in, goal_path_regions_table::out) is det.
record_non_local_regions(RevPath, Created, Removed, !NonLocalRegionProc) :-
(
RevPath = rgp_cons(RevInitialPath, LastStep),
( if LastStep = step_ite_else then
% The current NonLocalRegions are attached to the goal path
% to the corresponding condition.
RevPathToCond = rgp_cons(RevInitialPath, step_ite_cond),
( if
map.search(!.NonLocalRegionProc, RevPathToCond,
NonLocalRegions0)
then
set.union(NonLocalRegions0, Created, NonLocalRegions1),
set.difference(NonLocalRegions1, Removed, NonLocalRegions)
else
set.difference(Created, Removed, NonLocalRegions)
),
% Only record if some non-local region(s) exist.
( if set.is_empty(NonLocalRegions) then
true
else
map.set(RevPathToCond, NonLocalRegions, !NonLocalRegionProc)
)
else
true
),
% Need to update the non-local sets of outer if-then-elses of this one,
% if any.
record_non_local_regions(RevInitialPath, Created, Removed,
!NonLocalRegionProc)
;
RevPath = rgp_nil
).
:- pred collect_non_local_regions_in_ite_compound_goal(rpt_graph::in,
pp_region_set_table::in, pp_region_set_table::in,
rbmm_renaming_proc::in, rbmm_renaming_annotation_proc::in, hlds_goal::in,
goal_path_regions_table::in, goal_path_regions_table::out) is det.
collect_non_local_regions_in_ite_compound_goal(Graph, LRBeforeProc,
LRAfterProc, ResurRenamingProc, ResurRenamingAnnoProc,
GoalInIte, !NonLocalRegionProc) :-
GoalInIte = hlds_goal(Expr, _),
(
Expr = conj(_, [Conj | Conjs]),
list.foldl(
collect_non_local_regions_in_ite(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc),
[Conj | Conjs], !NonLocalRegionProc)
;
Expr = disj([Disj | Disjs]),
list.foldl(
collect_non_local_regions_in_ite(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc),
[Disj | Disjs], !NonLocalRegionProc)
;
Expr = switch(_, _, Cases),
list.foldl(
collect_non_local_regions_in_ite_case(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc),
Cases, !NonLocalRegionProc)
;
Expr = negation(Goal),
collect_non_local_regions_in_ite(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc,
Goal, !NonLocalRegionProc)
;
Expr = scope(_, Goal),
% XXX We should special-case the handling of from_ground_term_construct
% scopes.
collect_non_local_regions_in_ite(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc,
Goal, !NonLocalRegionProc)
;
Expr = if_then_else(_, Cond, Then, Else),
collect_non_local_regions_in_ite(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc,
Cond, !NonLocalRegionProc),
collect_non_local_regions_in_ite(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc,
Then, !NonLocalRegionProc),
collect_non_local_regions_in_ite(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc,
Else, !NonLocalRegionProc)
;
( Expr = unify(_, _, _, _, _)
; Expr = plain_call(_, _, _, _, _, _)
; Expr = conj(_, [])
; Expr = disj([])
; Expr = call_foreign_proc(_, _, _, _, _, _, _)
; Expr = generic_call(_, _, _, _, _)
; Expr = shorthand(_)
),
unexpected($pred, "atomic or unsupported goal")
).
:- pred collect_non_local_regions_in_ite_case(rpt_graph::in,
pp_region_set_table::in, pp_region_set_table::in,
rbmm_renaming_proc::in, rbmm_renaming_annotation_proc::in, case::in,
goal_path_regions_table::in, goal_path_regions_table::out) is det.
collect_non_local_regions_in_ite_case(Graph, LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc, Case, !NonLocalRegionProc) :-
Case = case(_, _, Goal),
collect_non_local_regions_in_ite(Graph, LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc, Goal, !NonLocalRegionProc).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
%
% Collect regions created inside condition goals of if-then-elses.
%
% The process here is very similar to that of
% collect_non_local_regions_in_ite predicate.
% The difference is that this predicate is used only in the scope of
% a condition goal.
%
:- pred collect_regions_created_in_condition(rpt_graph::in,
pp_region_set_table::in, pp_region_set_table::in,
rbmm_renaming_proc::in, rbmm_renaming_annotation_proc::in, hlds_goal::in,
goal_path_regions_table::in, goal_path_regions_table::out) is det.
collect_regions_created_in_condition(Graph, LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc, Cond, !InCondRegionsProc) :-
Cond = hlds_goal(CondExpr, CondInfo),
HasSubGoals = goal_expr_has_subgoals(CondExpr),
(
HasSubGoals = does_not_have_subgoals,
ProgPoint = program_point_init(CondInfo),
ProgPoint = pp(_, RevGoalPath),
map.lookup(LRBeforeProc, ProgPoint, LRBefore),
map.lookup(LRAfterProc, ProgPoint, LRAfter),
set.difference(LRAfter, LRBefore, CreatedNodes),
% We need to apply renaming to this CreatedNodes set and look up
% the renaming annotations after this program point. For each renaming
% annotation the left one is created and the right is removed.
( if map.search(ResurRenamingProc, ProgPoint, ResurRenaming0) then
ResurRenaming = ResurRenaming0
else
ResurRenaming = map.init
),
set.fold(apply_region_renaming(Graph, ResurRenaming),
CreatedNodes, set.init, CreatedRegions0),
( if
map.search(ResurRenamingAnnoProc, ProgPoint, ResurRenamingAnnos0)
then
ResurRenamingAnnos = ResurRenamingAnnos0
else
ResurRenamingAnnos = []
),
list.foldl2(renaming_annotation_to_regions, ResurRenamingAnnos,
set.init, LeftRegions,
set.init, _RightRegions),
set.union(CreatedRegions0, LeftRegions, CreatedRegions),
record_regions_created_in_condition(RevGoalPath,
CreatedRegions, !InCondRegionsProc)
;
HasSubGoals = has_subgoals,
collect_regions_created_in_condition_compound_goal(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc,
Cond, !InCondRegionsProc)
).
% The regions created inside the condition of an if-then-else will
% be attached to the goal path to the condition.
%
% We need to update the sets of all the conditions surrounding this
% program point.
%
:- pred record_regions_created_in_condition(reverse_goal_path::in,
set(string)::in, goal_path_regions_table::in,
goal_path_regions_table::out) is det.
record_regions_created_in_condition(RevPath, Created, !InCondRegionsProc) :-
(
RevPath = rgp_cons(RevInitialPath, LastStep),
( if LastStep = step_ite_cond then
( if map.search(!.InCondRegionsProc, RevPath, InCondRegions0) then
set.union(InCondRegions0, Created, InCondRegions)
else
InCondRegions = Created
),
% Only record if some regions are actually created inside
% the condition.
( if set.is_empty(InCondRegions) then
true
else
map.set(RevPath, InCondRegions, !InCondRegionsProc)
)
else
true
),
record_regions_created_in_condition(RevInitialPath, Created,
!InCondRegionsProc)
;
RevPath = rgp_nil
).
:- pred collect_regions_created_in_condition_compound_goal(rpt_graph::in,
pp_region_set_table::in, pp_region_set_table::in,
rbmm_renaming_proc::in, rbmm_renaming_annotation_proc::in, hlds_goal::in,
goal_path_regions_table::in, goal_path_regions_table::out) is det.
collect_regions_created_in_condition_compound_goal(Graph,
LRBeforeProc, LRAfterProc, ResurRenamingProc, ResurRenamingAnnoProc,
GoalInIte, !InCondRegionsProc) :-
GoalInIte = hlds_goal(Expr, _),
(
Expr = conj(_, [Conj | Conjs]),
list.foldl(
collect_regions_created_in_condition(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc),
[Conj | Conjs], !InCondRegionsProc)
;
Expr = disj([Disj | Disjs]),
list.foldl(
collect_regions_created_in_condition(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc),
[Disj | Disjs], !InCondRegionsProc)
;
Expr = switch(_, _, Cases),
list.foldl(
collect_regions_created_in_condition_case(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc),
Cases, !InCondRegionsProc)
;
Expr = negation(Goal),
collect_regions_created_in_condition(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc,
Goal, !InCondRegionsProc)
;
Expr = scope(_, Goal),
% XXX We should special-case the handling of from_ground_term_construct
% scopes.
collect_regions_created_in_condition(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc,
Goal, !InCondRegionsProc)
;
Expr = if_then_else(_, Cond, Then, Else),
collect_regions_created_in_condition(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc,
Cond, !InCondRegionsProc),
collect_regions_created_in_condition(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc,
Then, !InCondRegionsProc),
collect_regions_created_in_condition(Graph,
LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc,
Else, !InCondRegionsProc)
;
( Expr = unify(_, _, _, _, _)
; Expr = plain_call(_, _, _, _, _, _)
; Expr = conj(_, [])
; Expr = disj([])
; Expr = call_foreign_proc(_, _, _, _, _, _, _)
; Expr = generic_call(_, _, _, _, _)
; Expr = shorthand(_)
),
unexpected($pred, "atomic or unsupported goal")
).
:- pred collect_regions_created_in_condition_case(rpt_graph::in,
pp_region_set_table::in, pp_region_set_table::in,
rbmm_renaming_proc::in, rbmm_renaming_annotation_proc::in, case::in,
goal_path_regions_table::in, goal_path_regions_table::out) is det.
collect_regions_created_in_condition_case(Graph,
LRBeforeProc, LRAfterProc, ResurRenamingProc, ResurRenamingAnnoProc,
Case, !InCondRegionsProc) :-
Case = case(_, _, Goal),
collect_regions_created_in_condition(Graph, LRBeforeProc, LRAfterProc,
ResurRenamingProc, ResurRenamingAnnoProc, Goal, !InCondRegionsProc).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
%
% Collect regions that need to be renamed, i.e., both created in a condition
% goal and non-local to the corresponding if-then-else.
%
collect_ite_renamed_regions(InCondRegionsTable, NonLocalRegionsTable,
IteRenamedRegionsTable) :-
map.foldl(collect_ite_renamed_regions_proc(NonLocalRegionsTable),
InCondRegionsTable, map.init, IteRenamedRegionsTable).
:- pred collect_ite_renamed_regions_proc(proc_goal_path_regions_table::in,
pred_proc_id::in, goal_path_regions_table::in,
proc_goal_path_regions_table::in, proc_goal_path_regions_table::out)
is det.
collect_ite_renamed_regions_proc(NonLocalRegionsTable, PPId,
InCondRegionsProc, !IteRenamedRegionTable) :-
( if map.search(NonLocalRegionsTable, PPId, NonLocalRegionsProc) then
map.foldl(collect_ite_renamed_regions_ite(NonLocalRegionsProc),
InCondRegionsProc, map.init, IteRenamedRegionProc),
( if map.count(IteRenamedRegionProc) = 0 then
true
else
map.set(PPId, IteRenamedRegionProc, !IteRenamedRegionTable)
)
else
true
).
:- pred collect_ite_renamed_regions_ite(goal_path_regions_table::in,
reverse_goal_path::in, set(string)::in,
goal_path_regions_table::in, goal_path_regions_table::out) is det.
collect_ite_renamed_regions_ite(NonLocalRegionsProc, PathToCond,
InCondRegions, !IteRenamedRegionProc) :-
( if map.search(NonLocalRegionsProc, PathToCond, NonLocalRegions) then
set.intersect(NonLocalRegions, InCondRegions, RenamedRegions),
( if set.is_empty(RenamedRegions) then
true
else
map.set(PathToCond, RenamedRegions, !IteRenamedRegionProc)
)
else
true
).
%---------------------------------------------------------------------------%
%
% Derive necessary renaming.
%
collect_ite_renaming(ModuleInfo, RptaInfoTable, IteRenamedRegionTable,
IteRenamingTable) :-
map.foldl(collect_ite_renaming_proc(ModuleInfo, RptaInfoTable),
IteRenamedRegionTable, map.init, IteRenamingTable).
:- pred collect_ite_renaming_proc(module_info::in, rpta_info_table::in,
pred_proc_id::in, goal_path_regions_table::in,
rbmm_renaming_table::in, rbmm_renaming_table::out) is det.
collect_ite_renaming_proc(ModuleInfo, RptaInfoTable,
PPId, IteRenamedRegionProc, !IteRenamingTable) :-
module_info_proc_info(ModuleInfo, PPId, ProcInfo0),
fill_goal_path_slots_in_proc(ModuleInfo, ProcInfo0, ProcInfo),
proc_info_get_goal(ProcInfo, Goal),
map.lookup(RptaInfoTable, PPId, RptaInfo),
RptaInfo = rpta_info(Graph, _),
collect_ite_renaming_goal(IteRenamedRegionProc, Graph,
Goal, map.init, IteRenamingProc),
map.set(PPId, IteRenamingProc, !IteRenamingTable).
:- pred collect_ite_renaming_goal(goal_path_regions_table::in, rpt_graph::in,
hlds_goal::in, rbmm_renaming_proc::in, rbmm_renaming_proc::out) is det.
collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Goal,
!IteRenamingProc) :-
Goal = hlds_goal(GoalExpr, _),
(
( GoalExpr = unify(_, _, _, _, _)
; GoalExpr = plain_call(_, _, _, _, _, _)
; GoalExpr = generic_call(_, _, _, _, _)
; GoalExpr = call_foreign_proc(_, _, _, _, _, _, _)
)
;
GoalExpr = conj(_, Conjs),
list.foldl(collect_ite_renaming_goal(IteRenamedRegionProc, Graph),
Conjs, !IteRenamingProc)
;
GoalExpr = disj(Disjs),
list.foldl(collect_ite_renaming_goal(IteRenamedRegionProc, Graph),
Disjs, !IteRenamingProc)
;
GoalExpr = switch(_, _, Cases),
list.foldl(collect_ite_renaming_case(IteRenamedRegionProc, Graph),
Cases, !IteRenamingProc)
;
GoalExpr = negation(SubGoal),
collect_ite_renaming_goal(IteRenamedRegionProc, Graph,
SubGoal, !IteRenamingProc)
;
GoalExpr = scope(_, SubGoal),
% XXX We should special-case the handling of from_ground_term_construct
% scopes.
collect_ite_renaming_goal(IteRenamedRegionProc, Graph,
SubGoal, !IteRenamingProc)
;
GoalExpr = if_then_else(_, Cond, Then, Else),
% Renaming for if-then-else only happens in condition goals.
collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph,
Cond, !IteRenamingProc),
collect_ite_renaming_goal(IteRenamedRegionProc, Graph,
Then, !IteRenamingProc),
collect_ite_renaming_goal(IteRenamedRegionProc, Graph,
Else, !IteRenamingProc)
;
GoalExpr = shorthand(_),
unexpected($pred, "shorthand")
).
:- pred collect_ite_renaming_case(goal_path_regions_table::in, rpt_graph::in,
case::in, rbmm_renaming_proc::in, rbmm_renaming_proc::out) is det.
collect_ite_renaming_case(IteRenamedRegionProc, Graph,
Case, !IteRenamingProc) :-
Case = case(_, _, Goal),
collect_ite_renaming_goal(IteRenamedRegionProc, Graph,
Goal, !IteRenamingProc).
% Introduce renaming for each program point in a condition goal.
%
:- pred collect_ite_renaming_in_condition(goal_path_regions_table::in,
rpt_graph::in, hlds_goal::in,
rbmm_renaming_proc::in, rbmm_renaming_proc::out) is det.
collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph, Cond,
!IteRenamingProc) :-
Cond = hlds_goal(CondExpr, CondInfo),
HasSubGoals = goal_expr_has_subgoals(CondExpr),
(
HasSubGoals = does_not_have_subgoals,
ProgPoint = program_point_init(CondInfo),
% It is enough to look for the regions to be renamed at the closest
% condition because if a region is to be renamed for a compounding
% if-then-else of the closest if-then-else then it also needs to be
% renamed for the closest if-then-else.
ProgPoint = pp(_, RevGoalPath),
get_closest_condition_in_goal_path(RevGoalPath, RevPathToClosestCond,
0, HowMany),
( if
map.search(IteRenamedRegionProc, RevPathToClosestCond,
RenamedRegions)
then
set.fold(record_ite_renaming(ProgPoint, HowMany, Graph),
RenamedRegions, !IteRenamingProc)
else
% No region needs to be renamed due to if-then-else covering
% this program point.
true
)
;
HasSubGoals = has_subgoals,
collect_ite_renaming_in_condition_compound_goal( IteRenamedRegionProc,
Graph, Cond, !IteRenamingProc)
).
% A renaming is of the form: R --> R_ite_HowMany.
%
:- pred record_ite_renaming(program_point::in, int::in, rpt_graph::in,
string::in, rbmm_renaming_proc::in, rbmm_renaming_proc::out) is det.
record_ite_renaming(ProgPoint, HowMany, _Graph, RegName, !IteRenamingProc) :-
NewName = RegName ++ "_ite_" ++ string.int_to_string(HowMany),
( if map.search(!.IteRenamingProc, ProgPoint, IteRenaming0) then
map.set(RegName, [NewName], IteRenaming0, IteRenaming)
else
map.set(RegName, [NewName], map.init, IteRenaming)
),
map.set(ProgPoint, IteRenaming, !IteRenamingProc).
:- pred collect_ite_renaming_in_condition_compound_goal(
goal_path_regions_table::in, rpt_graph::in,
hlds_goal::in, rbmm_renaming_proc::in, rbmm_renaming_proc::out) is det.
collect_ite_renaming_in_condition_compound_goal(IteRenamedRegionProc,
Graph, GoalInCond, !IteRenamingProc) :-
GoalInCond = hlds_goal(Expr, _),
(
Expr = conj(_, [Conj | Conjs]),
list.foldl(
collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph),
[Conj | Conjs], !IteRenamingProc)
;
Expr = disj([Disj | Disjs]),
list.foldl(
collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph),
[Disj | Disjs], !IteRenamingProc)
;
Expr = switch(_, _, Cases),
list.foldl(
collect_ite_renaming_in_condition_case(IteRenamedRegionProc,
Graph),
Cases, !IteRenamingProc)
;
Expr = negation(Goal),
collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph, Goal,
!IteRenamingProc)
;
Expr = scope(_, Goal),
% XXX We should special-case the handling of from_ground_term_construct
% scopes.
collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph, Goal,
!IteRenamingProc)
;
Expr = if_then_else(_, Cond, Then, Else),
collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph,
Cond, !IteRenamingProc),
collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph,
Then, !IteRenamingProc),
collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph,
Else, !IteRenamingProc)
;
( Expr = unify(_, _, _, _, _)
; Expr = plain_call(_, _, _, _, _, _)
; Expr = conj(_, [])
; Expr = disj([])
; Expr = call_foreign_proc(_, _, _, _, _, _, _)
; Expr = generic_call(_, _, _, _, _)
; Expr = shorthand(_)
),
unexpected($pred, "atomic or unsupported goal")
).
:- pred collect_ite_renaming_in_condition_case(goal_path_regions_table::in,
rpt_graph::in, case::in,
rbmm_renaming_proc::in, rbmm_renaming_proc::out) is det.
collect_ite_renaming_in_condition_case(IteRenamedRegionProc, Graph, Case,
!IteRenamingProc) :-
Case = case(_, _, Goal),
collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph, Goal,
!IteRenamingProc).
% This predicate receives a goal path (to some goal) and returns
% the subpath to the closest condition containing the goal (if any);
% if the goal is not in any condition, the output path is empty.
% It also returns the number of conditions that contain the goal.
% e.g., ( if
% ( if
% goal
% ...
% then HowMany is 2.
%
% XXX should do this without goalpaths, with just goal parents.
%
:- pred get_closest_condition_in_goal_path(reverse_goal_path::in,
reverse_goal_path::out, int::in, int::out) is det.
get_closest_condition_in_goal_path(RevPath, RevPathToCond, !HowMany) :-
(
RevPath = rgp_cons(RevInitialPath, LastStep),
( if LastStep = step_ite_cond then
RevPathToCond = RevPath,
get_closest_condition_in_goal_path(RevInitialPath, _, !HowMany),
!:HowMany = !.HowMany + 1
else
get_closest_condition_in_goal_path(RevInitialPath, RevPathToCond,
!HowMany)
)
;
RevPath = rgp_nil,
RevPathToCond = rgp_nil
).
%---------------------------------------------------------------------------%
%
% Derive necessary reverse renaming.
%
collect_ite_annotation(IteRenamedRegionTable, ExecPathTable, 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, pred_proc_id::in, goal_path_regions_table::in,
rbmm_renaming_table::in, rbmm_renaming_table::out,
rbmm_renaming_annotation_table::in, rbmm_renaming_annotation_table::out)
is det.
collect_ite_annotation_proc(ExecPathTable, RptaInfoTable, PPId,
IteRenamedRegionProc, !IteRenamingTable, !IteAnnotationTable) :-
map.lookup(ExecPathTable, PPId, ExecPaths),
map.lookup(RptaInfoTable, PPId, RptaInfo),
map.lookup(!.IteRenamingTable, PPId, IteRenamingProc0),
RptaInfo = rpta_info(Graph, _),
map.foldl2(collect_ite_annotation_region_names(ExecPaths, Graph),
IteRenamedRegionProc, IteRenamingProc0, IteRenamingProc,
map.init, IteAnnotationProc),
map.set(PPId, IteAnnotationProc, !IteAnnotationTable),
map.set(PPId, IteRenamingProc, !IteRenamingTable).
:- pred collect_ite_annotation_region_names(list(execution_path)::in,
rpt_graph::in, reverse_goal_path::in, set(string)::in,
rbmm_renaming_proc::in, rbmm_renaming_proc::out,
rbmm_renaming_annotation_proc::in, rbmm_renaming_annotation_proc::out)
is det.
collect_ite_annotation_region_names(ExecPaths, Graph, RevPathToCond,
RenamedRegions, !IteRenamingProc, !IteAnnotationProc) :-
(
RevPathToCond = rgp_cons(RevInitialPath, LastStep),
expect(unify(LastStep, step_ite_cond), $pred, "not step_ite_cond"),
RevPathToThen = rgp_cons(RevInitialPath, step_ite_then),
get_closest_condition_in_goal_path(RevPathToCond, _, 0, HowMany),
list.foldl2(
collect_ite_annotation_exec_path(Graph, RevPathToThen,
RenamedRegions, HowMany),
ExecPaths, !IteRenamingProc, !IteAnnotationProc)
;
RevPathToCond = rgp_nil,
unexpected($pred, "empty path to condition")
).
:- pred collect_ite_annotation_exec_path(rpt_graph::in, reverse_goal_path::in,
set(string)::in, int::in, execution_path::in,
rbmm_renaming_proc::in, rbmm_renaming_proc::out,
rbmm_renaming_annotation_proc::in, rbmm_renaming_annotation_proc::out)
is det.
collect_ite_annotation_exec_path(_, _, _, _, [], !IteRenamingProc,
!IteAnnotationProc).
collect_ite_annotation_exec_path(Graph, PathToThen,
RenamedRegions, HowMany, [ProgPoint - _ | ProgPointGoals],
!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, ProgPointGoals, !IteRenamingProc,
!IteAnnotationProc).
% Process from the 2nd program point onwards.
%
:- pred collect_ite_annotation_exec_path_2(rpt_graph::in,
reverse_goal_path::in, set(string)::in, int::in, program_point::in,
execution_path::in, rbmm_renaming_proc::in, rbmm_renaming_proc::out,
rbmm_renaming_annotation_proc::in, rbmm_renaming_annotation_proc::out)
is det.
collect_ite_annotation_exec_path_2(_, _, _, _, _, [], !IteRenamingProc,
!IteAnnotationProc).
collect_ite_annotation_exec_path_2(Graph, RevPathToThen,
RenamedRegions, HowMany, PrevPoint, [ProgPoint - _ | ProgPointGoals],
!IteRenamingProc, !IteAnnotationProc) :-
ProgPoint = pp(_, RevGoalPath),
reverse_goal_path_to_steps(RevGoalPath, RevGoalPathSteps),
list.reverse(RevGoalPathSteps, GoalPathSteps),
reverse_goal_path_to_steps(RevPathToThen, RevPathToThenSteps),
list.reverse(RevPathToThenSteps, PathToThenSteps),
( if list.append(PathToThenSteps, FromThenSteps, GoalPathSteps) then
( if list.member(step_ite_cond, FromThenSteps) then
% 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.
( if map.search(!.IteRenamingProc, PrevPoint, PrevIteRenaming) then
map.set(ProgPoint, PrevIteRenaming, !IteRenamingProc)
else
true
),
collect_ite_annotation_exec_path_2(Graph, RevPathToThen,
RenamedRegions, HowMany, ProgPoint, ProgPointGoals,
!IteRenamingProc, !IteAnnotationProc)
else
% 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)
)
else
collect_ite_annotation_exec_path_2(Graph, RevPathToThen,
RenamedRegions, HowMany, ProgPoint, ProgPointGoals,
!IteRenamingProc, !IteAnnotationProc)
).
:- pred reverse_goal_path_to_steps(reverse_goal_path::in,
list(goal_path_step)::out) is det.
reverse_goal_path_to_steps(rgp_nil, []).
reverse_goal_path_to_steps(rgp_cons(EarlierPath, LaterStep),
[LaterStep | EarlierSteps]) :-
reverse_goal_path_to_steps(EarlierPath, EarlierSteps).
% The reverse renaming annotation is in the form: R = R_ite_HowMany.
% The annotation is attached to the program point but actually means
% to be added before the program point.
% If there exists a renaming at the program point related to R, e.g.,
% R --> R_1, then the annotation is R_1 = R_ite_HowMany.
%
:- pred introduce_reverse_renaming(program_point::in,
rbmm_renaming_proc::in, int::in, string::in,
rbmm_renaming_annotation_proc::in, rbmm_renaming_annotation_proc::out)
is det.
introduce_reverse_renaming(ProgPoint, IteRenamingProc, HowMany, RegName,
!IteAnnotationProc) :-
CurrentName = RegName ++ "_ite_" ++ string.int_to_string(HowMany),
( if map.search(IteRenamingProc, ProgPoint, Renaming) then
( if map.search(Renaming, RegName, RenameToList) then
( if list.length(RenameToList) = 1 then
RenameTo = list.det_last(RenameToList),
make_renaming_instruction(CurrentName, RenameTo, Annotation)
else
unexpected($pred, "more than one renaming")
)
else
make_renaming_instruction(CurrentName, RegName, Annotation)
)
else
% No renaming exists at this program point.
make_renaming_instruction(CurrentName, RegName, Annotation)
),
record_annotation(ProgPoint, Annotation, !IteAnnotationProc).
%---------------------------------------------------------------------------%
:- end_module transform_hlds.rbmm.condition_renaming.
%---------------------------------------------------------------------------%