Files
mercury/compiler/rbmm.interproc_region_lifetime.m
Zoltan Somogyi fbbe86b494 Make rbmm.m only a package.
compiler/rbmm.m:
compiler/rbmm.region_analysis.m:
    Move all the code (one predicate) out of rbmm.m to the new module
    rbmm.region_analysis.m, leaving it containing nothing but
    include_module declarations.

    Delete the unneeded !IO argument pair of that predicate.

compiler/mercury_compile_middle_passes.m:
    Don't pass the !IO arguments to that predicate.

compiler/notes/compiler_design.html:
    This file has not mentioned the rbmm package until now.
    Add a short description of the package itself, but since I don't
    really know what each of its component modules do, I cannot add
    even short descriptions of them.

compiler/rbmm.condition_renaming.m:
compiler/rbmm.execution_path.m:
compiler/rbmm.interproc_region_lifetime.m:
compiler/rbmm.live_region_analysis.m:
compiler/rbmm.live_variable_analysis.m:
compiler/rbmm.points_to_analysis.m:
compiler/rbmm.points_to_info.m:
compiler/rbmm.region_arguments.m:
compiler/rbmm.region_instruction.m:
compiler/rbmm.region_resurrection_renaming.m:
compiler/rbmm.region_transformation.m:
    Conform to the changes above.
2022-05-01 04:57:04 +10:00

595 lines
25 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 2005-2007, 2009-2011 The University of Melbourne.
% Copyright (C) 2017 The Mercury Team.
% 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.interproc_region_lifetime.m.
% Main author: Quan Phan.
%
% This module detects lifetime of regions across procedure boundary. It
% updates the initial bornR and deadR, then computing constantR for each
% procedure. It also provides a predicate to eliminate primitive regions
% (i.e., ones that do not actually exist if primitive values are not boxed)
% from analysis information.
%
%---------------------------------------------------------------------------%
:- module transform_hlds.rbmm.interproc_region_lifetime.
:- interface.
:- import_module hlds.
:- import_module hlds.hlds_module.
:- import_module transform_hlds.rbmm.points_to_info.
:- import_module transform_hlds.rbmm.region_liveness_info.
%---------------------------------------------------------------------------%
% This predicate reasons about lifetime of regions across procedure
% boundary. It will update the initial deadR and bornR sets and compute
% constantR set.
%
:- pred compute_interproc_region_lifetime(module_info::in,
rpta_info_table::in, execution_path_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::out, proc_region_set_table::in,
proc_region_set_table::out, proc_region_set_table::in,
proc_region_set_table::out) is det.
% This predicate removes regions of primitive types from the input data
% structures.
% The reason for this is the assumption that primitive values are not
% boxed (i.e., not store in regions).
%
:- pred ignore_primitive_regions(module_info::in, rpta_info_table::in,
proc_region_set_table::in, proc_region_set_table::out,
proc_region_set_table::in, proc_region_set_table::out,
proc_region_set_table::in, proc_region_set_table::out,
proc_region_set_table::in, proc_region_set_table::out,
proc_pp_region_set_table::in, proc_pp_region_set_table::out,
proc_pp_region_set_table::in, proc_pp_region_set_table::out,
proc_pp_region_set_table::in, proc_pp_region_set_table::out) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module check_hlds.
:- import_module check_hlds.type_util.
:- import_module hlds.hlds_dependency_graph.
:- import_module hlds.hlds_goal.
:- import_module hlds.hlds_pred.
:- import_module libs.
:- import_module libs.dependency_graph.
:- import_module transform_hlds.rbmm.points_to_graph.
:- import_module transform_hlds.smm_common.
:- import_module assoc_list.
:- import_module list.
:- import_module map.
:- import_module maybe.
:- import_module pair.
:- import_module set.
:- import_module solutions.
%---------------------------------------------------------------------------%
%
% Computing across procedure region lifetime.
%
compute_interproc_region_lifetime(ModuleInfo, RptaInfoTable, ExecPathTable,
LRBeforeTable, LRAfterTable, InputRTable, OutputRTable,
ConstantRTable, !BornRTable, !DeadRTable) :-
apply_live_region_born_removal_rules(ModuleInfo, RptaInfoTable,
ExecPathTable, LRBeforeTable, LRAfterTable, !BornRTable),
apply_live_region_dead_removal_rules(ModuleInfo, RptaInfoTable,
ExecPathTable, LRBeforeTable, LRAfterTable, !DeadRTable),
map.foldl(compute_constantR(InputRTable, OutputRTable, !.BornRTable),
!.DeadRTable, map.init, ConstantRTable).
:- pred compute_constantR(proc_region_set_table::in,
proc_region_set_table::in, proc_region_set_table::in,
pred_proc_id::in, region_set::in, proc_region_set_table::in,
proc_region_set_table::out) is det.
compute_constantR(InputRTable, OutputRTable, BornRTable, PPId, DeadR,
!ConstantRTable) :-
map.lookup(InputRTable, PPId, InputR),
map.lookup(OutputRTable, PPId, OutputR),
map.lookup(BornRTable, PPId, BornR),
set.union(InputR, OutputR, InputOutputR0),
set.difference(InputOutputR0, BornR, InputOutputR),
set.difference(InputOutputR, DeadR, ConstantR),
map.set(PPId, ConstantR, !ConstantRTable).
% Apply the live region analysis rules to update bornR and deadR
% sets of each procedure.
%
:- pred apply_live_region_dead_removal_rules(module_info::in,
rpta_info_table::in, execution_path_table::in,
proc_pp_region_set_table::in, proc_pp_region_set_table::in,
proc_region_set_table::in, proc_region_set_table::out) is det.
apply_live_region_dead_removal_rules(ModuleInfo, RptaInfoTable, ExecPathTable,
LRBeforeTable, LRAfterTable, !DeadRTable) :-
apply_live_region_rule(dead_removal_rules, ModuleInfo, RptaInfoTable,
ExecPathTable, LRBeforeTable, LRAfterTable, !DeadRTable).
:- pred apply_live_region_born_removal_rules(module_info::in,
rpta_info_table::in, execution_path_table::in,
proc_pp_region_set_table::in, proc_pp_region_set_table::in,
proc_region_set_table::in, proc_region_set_table::out) is det.
apply_live_region_born_removal_rules(ModuleInfo, RptaInfoTable, ExecPathTable,
LRBeforeTable, LRAfterTable, !BornRTable) :-
apply_live_region_rule(born_removal_rules, ModuleInfo, RptaInfoTable,
ExecPathTable, LRBeforeTable, LRAfterTable, !BornRTable).
:- type rule_pred ==
(pred(pred_proc_id, region_set, region_set, proc_region_set_table,
rpt_call_alpha_mapping, region_set)).
:- inst rule_pred == (pred(in, in, in, in, in, out) is det).
:- pred apply_live_region_rule(rule_pred::in(rule_pred), module_info::in,
rpta_info_table::in, execution_path_table::in,
proc_pp_region_set_table::in, proc_pp_region_set_table::in,
proc_region_set_table::in, proc_region_set_table::out) is det.
apply_live_region_rule(Rule, ModuleInfo, RptaInfoTable, ExecPathTable,
LRBeforeTable, LRAfterTable, !ProcRegionSetTable) :-
module_info_ensure_dependency_info(ModuleInfo, ModuleInfo1, DepInfo),
BottomUpSCCs = dependency_info_get_bottom_up_sccs(DepInfo),
run_with_dependencies(Rule, BottomUpSCCs, ModuleInfo1,
RptaInfoTable, ExecPathTable, LRBeforeTable, LRAfterTable,
!ProcRegionSetTable).
:- pred run_with_dependencies(rule_pred::in(rule_pred),
hlds_bottom_up_dependency_sccs::in, module_info::in, rpta_info_table::in,
execution_path_table::in, proc_pp_region_set_table::in,
proc_pp_region_set_table::in, proc_region_set_table::in,
proc_region_set_table::out) is det.
run_with_dependencies(Rule, BottomUpSCCs, ModuleInfo, RptaInfoTable,
ExecPathTable, LRBeforeTable, LRAfterTable, !ProcRegionSetTable) :-
% We want to proceed the SCC graph top-down so reverse the list
% (the process is foldr2, but it is not yet in list module)
list.reverse(BottomUpSCCs, TopDownSCCs),
list.foldl(
run_with_dependency(Rule, ModuleInfo, RptaInfoTable,
ExecPathTable, LRBeforeTable, LRAfterTable),
TopDownSCCs, !ProcRegionSetTable).
:- pred run_with_dependency(rule_pred::in(rule_pred),
module_info::in, rpta_info_table::in, execution_path_table::in,
proc_pp_region_set_table::in, proc_pp_region_set_table::in,
set(pred_proc_id)::in,
proc_region_set_table::in, proc_region_set_table::out) is det.
run_with_dependency(Rule, ModuleInfo, RptaInfoTable, ExecPathTable,
LRBeforeTable, LRAfterTable, SCC, !ProcRegionSetTable) :-
% Ignores special predicates.
( if some_are_special_preds(set.to_sorted_list(SCC), ModuleInfo) then
true
else
% Perform a fixpoint computation for each strongly connected
% component.
run_with_dependency_until_fixpoint(Rule, SCC, ModuleInfo,
RptaInfoTable, ExecPathTable, LRBeforeTable, LRAfterTable,
!ProcRegionSetTable)
).
:- pred run_with_dependency_until_fixpoint(rule_pred::in(rule_pred),
scc::in, module_info::in, rpta_info_table::in,
execution_path_table::in,
proc_pp_region_set_table::in, proc_pp_region_set_table::in,
proc_region_set_table::in, proc_region_set_table::out) is det.
run_with_dependency_until_fixpoint(Rule, SCC, ModuleInfo, RptaInfoTable,
ExecPathTable, LRBeforeTable, LRAfterTable, !ProcRegionSetTable) :-
% This call calculates the region set for each procedure in SCC.
set.foldl(apply_rule_pred_proc(Rule, ModuleInfo, RptaInfoTable,
ExecPathTable, LRBeforeTable, LRAfterTable),
SCC, !.ProcRegionSetTable, ProcRegionSetTable1),
( if
proc_region_set_table_equal(ProcRegionSetTable1, !.ProcRegionSetTable)
then
% If all region_set's in the FPTable are intact update the main
% ProcRegionSetTable.
!:ProcRegionSetTable = ProcRegionSetTable1
else
% Some is not fixed, start all over again
run_with_dependency_until_fixpoint(Rule, SCC, ModuleInfo,
RptaInfoTable, ExecPathTable, LRBeforeTable, LRAfterTable,
ProcRegionSetTable1, !:ProcRegionSetTable)
).
:- pred apply_rule_pred_proc(rule_pred::in(rule_pred),
module_info::in, rpta_info_table::in, execution_path_table::in,
proc_pp_region_set_table::in, proc_pp_region_set_table::in,
pred_proc_id::in, proc_region_set_table::in, proc_region_set_table::out)
is det.
apply_rule_pred_proc(Rule, ModuleInfo, RptaInfoTable, ExecPathTable,
LRBeforeTable, LRAfterTable, PPId, !ProcRegionSetTable) :-
% We need to follow each execution path and apply the two rules when
% possible
map.lookup(RptaInfoTable, PPId, RptaInfo),
map.lookup(ExecPathTable, PPId, EPs),
map.lookup(LRBeforeTable, PPId, ProcLRBefore),
map.lookup(LRAfterTable, PPId, ProcLRAfter),
% Here we analysing a caller but will update the region sets of its
% callees.
apply_live_region_rules_exec_paths(Rule, EPs, ExecPathTable, ModuleInfo,
PPId, RptaInfo, RptaInfoTable, ProcLRBefore, ProcLRAfter,
!ProcRegionSetTable).
:- pred apply_live_region_rules_exec_paths(rule_pred::in(rule_pred),
list(execution_path)::in, execution_path_table::in, module_info::in,
pred_proc_id::in, rpta_info::in, rpta_info_table::in,
pp_region_set_table::in, pp_region_set_table::in,
proc_region_set_table::in, proc_region_set_table::out) is det.
apply_live_region_rules_exec_paths(_Rule, [], _, _, _, _, _, _, _,
!ProcRegionSetTable).
apply_live_region_rules_exec_paths(Rule, [ExecPath|ExecPaths], ExecPathTable,
ModuleInfo, PPId, RptaInfo, RptaInfoTable, ProcLRBefore,
ProcLRAfter, !ProcRegionSetTable) :-
apply_live_region_rules_exec_path(Rule, ExecPath, ExecPathTable,
ModuleInfo, PPId, RptaInfo, RptaInfoTable, ProcLRBefore, ProcLRAfter,
!ProcRegionSetTable),
apply_live_region_rules_exec_paths(Rule, ExecPaths, ExecPathTable,
ModuleInfo, PPId, RptaInfo, RptaInfoTable, ProcLRBefore, ProcLRAfter,
!ProcRegionSetTable).
% Follow each execution path of a procedure and update deadR and bornR
% sets.
%
:- pred apply_live_region_rules_exec_path(rule_pred::in(rule_pred),
execution_path::in, execution_path_table::in, module_info::in,
pred_proc_id::in, rpta_info::in, rpta_info_table::in,
pp_region_set_table::in, pp_region_set_table::in,
proc_region_set_table::in, proc_region_set_table::out) is det.
apply_live_region_rules_exec_path(_Rule, [], _, _, _, _, _, _, _,
!ProcRegionSetTable).
apply_live_region_rules_exec_path(Rule, [ProgPoint - Goal | ProgPoint_Goals],
ExecPathTable, ModuleInfo, PPId, RptaInfo, RptaInfoTable,
ProcLRBefore, ProcLRAfter, !ProcRegionSetTable) :-
Goal = hlds_goal(Expr, _),
% The updating will only happen at call sites, i.e., when the goal
% at the program point is a procedure call.
( if Expr = plain_call(CalleePredId, CalleeProcId, _, _, _, _) then
CalleePPId = proc(CalleePredId, CalleeProcId),
( if
some_are_special_preds([CalleePPId], ModuleInfo)
then
true
else
RptaInfo = rpta_info(_, AlphaMapping),
map.lookup(AlphaMapping, ProgPoint, AlphaAtProgPoint),
map.lookup(ProcLRBefore, ProgPoint, LRBefore),
map.lookup(ProcLRAfter, ProgPoint, LRAfter),
% apply a rule
call(Rule, CalleePPId, LRBefore, LRAfter,
!.ProcRegionSetTable, AlphaAtProgPoint, RegionSet),
map.lookup(!.ProcRegionSetTable, CalleePPId, RegionSet0),
( if
set.equal(RegionSet, RegionSet0)
then
% i.e., no region is removed, so everything is the same
% as before
true
else
% some regions are removed, record the new set for q and ...
map.set(CalleePPId, RegionSet, !ProcRegionSetTable),
% ... those removals need to be propagated to the ones
% called by q
set.difference(RegionSet0, RegionSet, ToBeRemoved),
list.foldl(
remove_this_region_from_callees_of_proc(CalleePPId,
ExecPathTable, ModuleInfo, RptaInfoTable),
set.to_sorted_list(ToBeRemoved), !ProcRegionSetTable)
)
)
else
% ignore other sorts of goal
true
),
apply_live_region_rules_exec_path(Rule, ProgPoint_Goals, ExecPathTable,
ModuleInfo, PPId, RptaInfo, RptaInfoTable, ProcLRBefore, ProcLRAfter,
!ProcRegionSetTable).
%---------------------------------------------------------------------------%
%
% Live region analysis rules.
%
% Those rules ensure that:
% 1. when it is not safe for a procedure to remove a region, that region must
% not be in the procedure's deadR seti,
% 2. when a region exists before the procedure is called, that region must not
% be in the procedure's bornR set.
%
% Rules for eliminating regions from deadR set.
%
:- pred dead_removal_rules(pred_proc_id::in, region_set::in, region_set::in,
proc_region_set_table::in, rpt_call_alpha_mapping::in, region_set::out)
is det.
dead_removal_rules(Q_Id, LRBefore, LRAfter, DeadRTable, AlphaAtPP, DeadR_q) :-
% The current deadR of q.
map.lookup(DeadRTable, Q_Id, DeadR_q0),
% Apply dead removal rule L1 for r that is live before and after the
% call to q.
set.intersect(LRBefore, LRAfter, Rule1_Candidate),
set.fold(dead_removal_rule_1(AlphaAtPP), Rule1_Candidate,
DeadR_q0, DeadR_q1),
% Remove deadR rule L2.
targets_with_more_than_one_source(AlphaAtPP, Targets),
set.fold(dead_removal_rule_2(AlphaAtPP), Targets, DeadR_q1, DeadR_q).
:- pred dead_removal_rule_1(rpt_call_alpha_mapping::in, rptg_node::in,
region_set::in, region_set::out) is det.
dead_removal_rule_1(AlphaAtCallSite, Region, !DeadR_q) :-
% Find r' such that alpha(r') = Region.
solutions(map.inverse_search(AlphaAtCallSite, Region), SourceList),
set.list_to_set(SourceList, RPrimes),
% Remove any r' that is in deadR(q).
set.difference(!.DeadR_q, RPrimes, !:DeadR_q).
:- pred dead_removal_rule_2(rpt_call_alpha_mapping::in, rptg_node::in,
set(rptg_node)::in, set(rptg_node)::out) is det.
dead_removal_rule_2(AlphaAtCallSite, Region, !DeadR_q) :-
solutions(map.inverse_search(AlphaAtCallSite, Region), SourceList),
set.list_to_set(SourceList, RPrimes),
set.difference(!.DeadR_q, RPrimes, !:DeadR_q).
% rules for eliminating regions from bornR set.
%
:- pred born_removal_rules(pred_proc_id::in, region_set::in, region_set::in,
proc_region_set_table::in, rpt_call_alpha_mapping::in,
region_set::out) is det.
born_removal_rules(Q_Id, LRBefore, _, BornRTable, AlphaAtCallSite, BornR_q) :-
% The current bornR of q.
map.lookup(BornRTable, Q_Id, BornR_q0),
% Apply born removal rule L3 for r that is live before and after the
% call to q.
set.fold(born_removal_rule_1(AlphaAtCallSite), LRBefore,
BornR_q0, BornR_q1),
% remove bornR rule L4,
targets_with_more_than_one_source(AlphaAtCallSite, Targets),
set.fold(born_removal_rule_2(AlphaAtCallSite), Targets,
BornR_q1, BornR_q).
:- pred born_removal_rule_1(rpt_call_alpha_mapping::in, rptg_node::in,
set(rptg_node)::in, set(rptg_node)::out) is det.
born_removal_rule_1(AlphaAtCallSite, Region, !BornR_q) :-
solutions(map.inverse_search(AlphaAtCallSite, Region), SourceList),
set.list_to_set(SourceList, RPrimes),
set.difference(!.BornR_q, RPrimes, !:BornR_q).
% alpha(r') = r, alpha(r'') = r, r', r'' in bornR(q) imply remove r',
% r'' from bornR(q).
%
:- pred born_removal_rule_2(rpt_call_alpha_mapping::in, rptg_node::in,
set(rptg_node)::in, set(rptg_node)::out) is det.
born_removal_rule_2(AlphaAtCallSite, Region, !BornR_q) :-
solutions(map.inverse_search(AlphaAtCallSite, Region), SourceList),
set.list_to_set(SourceList, RPrimes),
set.difference(!.BornR_q, RPrimes, !:BornR_q).
% Find targets of alpha mapping that are mapped to by more than one
% source.
%
:- pred targets_with_more_than_one_source(rpt_call_alpha_mapping::in,
region_set::out) is det.
targets_with_more_than_one_source(AlphaAtCallSite, Targets) :-
map.foldl2(process_one_mapping, AlphaAtCallSite, set.init,
_Processed, set.init, Targets).
:- pred process_one_mapping(rptg_node::in, rptg_node::in, region_set::in,
region_set::out, region_set::in, region_set::out) is det.
process_one_mapping(_Source, Target, !Candidates, !Targets) :-
( if set.contains(!.Candidates, Target) then
set.insert(Target, !Targets)
else
set.insert(Target, !Candidates)
).
% This predicate propagates the removal of a region from a deadR or
% bornR sets of a procedure to the ones it calls, i.e., also remove
% the region from the corresponding sets of them.
%
:- pred remove_this_region_from_callees_of_proc(pred_proc_id::in,
execution_path_table::in, module_info::in, rpta_info_table::in,
rptg_node::in,
proc_region_set_table::in, proc_region_set_table::out) is det.
remove_this_region_from_callees_of_proc(PPId, ExecPathTable, ModuleInfo,
RptaInfoTable, Region, !ProcRegionSetTable) :-
% to have the goal at each pp
map.lookup(ExecPathTable, PPId, ExecPaths),
% Follow execution paths of this procedure and remove the region from
% this procedure's callees.
remove_this_from_eps(ExecPaths, PPId, Region, ExecPathTable,
ModuleInfo, RptaInfoTable, !ProcRegionSetTable).
% Follow each execution path of a procedure and update deadR and bornR
% sets.
%
:- pred remove_this_from_eps(list(execution_path)::in, pred_proc_id::in,
rptg_node::in, execution_path_table::in, module_info::in,
rpta_info_table::in,
proc_region_set_table::in, proc_region_set_table::out) is det.
remove_this_from_eps([], _, _, _, _, _, !ProcRegionSetTable).
remove_this_from_eps([ExecPath | ExecPaths], PPId, Region, ExecPathTable,
ModuleInfo, RptaInfoTable, !ProcRegionSetTable) :-
remove_this_from_ep(ExecPath, PPId, Region, ExecPathTable, ModuleInfo,
RptaInfoTable, !ProcRegionSetTable),
remove_this_from_eps(ExecPaths, PPId, Region, ExecPathTable, ModuleInfo,
RptaInfoTable, !ProcRegionSetTable).
:- pred remove_this_from_ep(execution_path::in, pred_proc_id::in,
rptg_node::in, execution_path_table::in, module_info::in,
rpta_info_table::in,
proc_region_set_table::in, proc_region_set_table::out) is det.
remove_this_from_ep([], _, _, _, _, _, !ProcRegionSetTable).
remove_this_from_ep([ProgPoint - Goal|ProgPoint_Goals], PPId,
ToBeRemovedRegion, ExecPathTable, ModuleInfo, RptaInfoTable,
!ProcRegionSetTable) :-
Goal = hlds_goal(Expr, _Info),
( if Expr = plain_call(CalleePredId, CalleeProcId, _, _, _, _) then
CalleePPId = proc(CalleePredId, CalleeProcId),
( if some_are_special_preds([CalleePPId], ModuleInfo) then
true
else
% Find the alpha mapping: alpha(_, R) = ToBeRemovedRegion
map.lookup(RptaInfoTable, PPId, RptaInfo_p),
RptaInfo_p = rpta_info(_Graph_p, AlphaMapping),
map.lookup(AlphaMapping, ProgPoint, AlphaAtCallSite),
map.foldl(find_alpha_source(ToBeRemovedRegion),
AlphaAtCallSite, set.init, Rs),
% Remove the sources from the RegionSet (either deadR or
% bornR) of this callee.
map.lookup(!.ProcRegionSetTable, CalleePPId,
RegionSet0),
set.difference(RegionSet0, Rs, RegionSet1),
% update the table and continue
( if set.equal(RegionSet0, RegionSet1) then
% no need to update
true
else
% Some is removed from deadR or bornR of this callee,
% so we update the entry of this called and analyse it.
map.set(CalleePPId, RegionSet1, !ProcRegionSetTable),
set.difference(RegionSet0, RegionSet1, RemovedFromQ),
% Call this one mutually recursively.
list.foldl(
remove_this_region_from_callees_of_proc(CalleePPId,
ExecPathTable, ModuleInfo, RptaInfoTable),
set.to_sorted_list(RemovedFromQ), !ProcRegionSetTable)
)
)
else
% ignore other sorts of goals
true
),
remove_this_from_ep(ProgPoint_Goals, PPId, ToBeRemovedRegion,
ExecPathTable, ModuleInfo, RptaInfoTable, !ProcRegionSetTable).
:- pred find_alpha_source(rptg_node::in, rptg_node::in, rptg_node::in,
set(rptg_node)::in, set(rptg_node)::out) is det.
find_alpha_source(ToBeRemovedRegion, Source, Target, !Rs) :-
( if ToBeRemovedRegion = Target then
set.insert(Source, !Rs)
else
true
).
%---------------------------------------------------------------------------%
%
% Eliminating primitive regions from live region analysis's information.
%
ignore_primitive_regions(ModuleInfo, RptaInfoTable, !BornRTable,
!DeadRTable, !ConstantRTable, !LocalRTable, !LRBeforeTable,
!LRAfterTable, !VoidVarRegionTable) :-
map.foldl(eliminate_primitive_regions(ModuleInfo, RptaInfoTable),
!.BornRTable, !BornRTable),
map.foldl(eliminate_primitive_regions(ModuleInfo, RptaInfoTable),
!.DeadRTable, !DeadRTable),
map.foldl(eliminate_primitive_regions(ModuleInfo, RptaInfoTable),
!.ConstantRTable, !ConstantRTable),
map.foldl(eliminate_primitive_regions(ModuleInfo, RptaInfoTable),
!.LocalRTable, !LocalRTable),
map.foldl(eliminate_primitive_regions_2(ModuleInfo, RptaInfoTable),
!.LRBeforeTable, !LRBeforeTable),
map.foldl(eliminate_primitive_regions_2(ModuleInfo, RptaInfoTable),
!.LRAfterTable, !LRAfterTable),
map.foldl(eliminate_primitive_regions_2(ModuleInfo, RptaInfoTable),
!.VoidVarRegionTable, !VoidVarRegionTable).
% Eliminate regions of primitive types from the proc_region_set_table.
%
:- pred eliminate_primitive_regions(module_info::in, rpta_info_table::in,
pred_proc_id::in, region_set::in,
proc_region_set_table::in, proc_region_set_table::out) is det.
eliminate_primitive_regions(ModuleInfo, RptaInfoTable, PPId, RegionSet0,
!RegionSetTable) :-
map.lookup(RptaInfoTable, PPId, RptaInfo),
RptaInfo = rpta_info(Graph, _Alpha),
set.fold(retain_non_primitive_regions(ModuleInfo, Graph), RegionSet0,
set.init, RegionSet),
map.det_update(PPId, RegionSet, !RegionSetTable).
:- pred retain_non_primitive_regions(module_info::in, rpt_graph::in,
rptg_node::in, region_set::in, region_set::out) is det.
retain_non_primitive_regions(ModuleInfo, Graph, Region, !RegionSet) :-
NodeType = rptg_lookup_node_type(Graph, Region),
( if type_not_stored_in_region(NodeType, ModuleInfo) then
true
else
set.insert(Region, !RegionSet)
).
% Eliminate regions of primitive types from the proc_pp_region_set_table.
%
:- pred eliminate_primitive_regions_2(module_info::in, rpta_info_table::in,
pred_proc_id::in, pp_region_set_table::in,
proc_pp_region_set_table::in, proc_pp_region_set_table::out) is det.
eliminate_primitive_regions_2(ModuleInfo, RptaInfoTable, PPId, LRProc0,
!LRTable) :-
map.lookup(RptaInfoTable, PPId, RptaInfo),
RptaInfo = rpta_info(Graph, _Alpha),
map.foldl(retain_non_primitive_regions_at_pp(ModuleInfo, Graph),
LRProc0, map.init, LRProc),
map.det_update(PPId, LRProc, !LRTable).
:- pred retain_non_primitive_regions_at_pp(module_info::in, rpt_graph::in,
program_point::in, region_set::in,
pp_region_set_table::in, pp_region_set_table::out) is det.
retain_non_primitive_regions_at_pp(ModuleInfo, Graph, ProgPoint,
RegionSet0, !LRProc) :-
set.fold(retain_non_primitive_regions(ModuleInfo, Graph), RegionSet0,
set.init, RegionSet),
map.set(ProgPoint, RegionSet, !LRProc).
%---------------------------------------------------------------------------%
:- end_module transform_hlds.rbmm.interproc_region_lifetime.
%---------------------------------------------------------------------------%