[m-rev.] For review: Filling in rbmm_goal_info field in goal_info
Quan Phan
quan.phan at cs.kuleuven.be
Tue Sep 4 22:17:21 AEST 2007
Hi,
Will anyone take a look at this diff for me? Or can I commit this
because it will likely not affect the other parts of the compiler.
Thanks and regards,
Quan.
On Wed, Aug 15, 2007 at 02:39:01AM +0200, Quan Phan wrote:
> Hi,
>
> Estimate hours taken: 15h.
> Branch: main.
>
> Implement the analysis to fill in the rbmm_goal_info field in the goal_info
> data structure. (Zoltan added this field several days ago.) This piece of
> information will be used by the code generator to optimize the runtime support
> needed for region-based memory management. It would be too much to describe
> how the information will be used here. I am writing up the runtime support
> needed for RBMM as the whole, which should include the explanation for this.
>
> compiler/rbmm.rbmm_goal_info_analysis.m:
> New file that contains the implementation of the analysis.
>
> compiler/hlds_goal.m:
> Add a function that initialize the rbmm_goal_info.
>
> compiler/hlds_out.m:
> Add an option, 'e' to --dump-hlds-options to print out rbmm_goal_info.
>
> compiler/rbmm.m:
> Include the new module and call the analysis.
>
> compiler/rbmm.actual_region_arguments.m:
> Change the data structure that represents actual region arguments to
> have there seperate lists for constant (carried), input (removed), and
> output (created) regions.
>
> compiler/type_util.m:
> Add a predicate that check whether the terms of a type will be stored
> in regions or not. This predicate must be consistent with the process
> of generating allocation in unify_gen.m.
>
> compiler/rbmm.interproc_region_lifetime.m:
> Change to use the new predicate in type_util.m.
>
> compiler/rbmm.region_transformation.m:
> Change to conform to the change in actual_region_arguments.m.
> Change to use the new predicate in type_util.m
>
> doc/user_guide.texi:
> Document the new option for --dump-hlds-options.
> Provide the missing description for the existing option 'R'.
>
> Regards,
> Quan.
>
> ? .hlds_goal.m.swp
> ? .rbmm.points_to_analysis.m.swp
> ? diff.19.35
> cvs diff: Diffing .
> Index: hlds_goal.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_goal.m,v
> retrieving revision 1.180
> diff -u -r1.180 hlds_goal.m
> --- hlds_goal.m 7 Aug 2007 07:09:54 -0000 1.180
> +++ hlds_goal.m 14 Aug 2007 23:41:09 -0000
> @@ -882,6 +882,8 @@
> used_regions :: set(prog_var)
> ).
>
> +:- func rbmm_info_init = rbmm_goal_info.
> +
> :- type mode_constr_goal_info
> ---> mode_constr_goal_info(
> % Inst_graph nodes that are reachable from variables
> @@ -1684,6 +1686,9 @@
>
> ctgc_goal_info_init = ctgc_goal_info(set.init, set.init, no_reuse_info).
>
> +rbmm_info_init = rbmm_goal_info(set.init, set.init, set.init, set.init,
> + set.init).
> +
> goal_info_get_determinism(GoalInfo) = GoalInfo ^ gi_determinism.
> goal_info_get_instmap_delta(GoalInfo) = GoalInfo ^ gi_instmap_delta.
> goal_info_get_nonlocals(GoalInfo) = GoalInfo ^ gi_nonlocals.
> Index: hlds_out.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_out.m,v
> retrieving revision 1.430
> diff -u -r1.430 hlds_out.m
> --- hlds_out.m 13 Aug 2007 03:01:40 -0000 1.430
> +++ hlds_out.m 14 Aug 2007 23:41:10 -0000
> @@ -1353,6 +1353,37 @@
> ;
> true
> ),
> + ( string.contains_char(Verbose, 'e') ->
> + MaybeRbmmInfo = goal_info_get_maybe_rbmm(GoalInfo),
> + (
> + MaybeRbmmInfo = yes(RbmmInfo),
> + RbmmInfo = rbmm_goal_info(Created, Removed, Carried, Alloc, Used),
> + write_indent(Indent, !IO),
> + io.write_string("% Created regions: ", !IO),
> + io.write_list(set.to_sorted_list(Created), ", ", io.write, !IO),
> + io.nl(!IO),
> + write_indent(Indent, !IO),
> + io.write_string("% Removed regions: ", !IO),
> + io.write_list(set.to_sorted_list(Removed), ", ", io.write, !IO),
> + io.nl(!IO),
> + write_indent(Indent, !IO),
> + io.write_string("% Carried regions: ", !IO),
> + io.write_list(set.to_sorted_list(Carried), ", ", io.write, !IO),
> + io.nl(!IO),
> + write_indent(Indent, !IO),
> + io.write_string("% Allocated into regions: ", !IO),
> + io.write_list(set.to_sorted_list(Alloc), ", ", io.write, !IO),
> + io.nl(!IO),
> + write_indent(Indent, !IO),
> + io.write_string("% Used regions: ", !IO),
> + io.write_list(set.to_sorted_list(Used), ", ", io.write, !IO),
> + io.nl(!IO)
> + ;
> + MaybeRbmmInfo = no
> + )
> + ;
> + true
> + ),
> ( string.contains_char(Verbose, 'z') ->
> Purity = goal_info_get_purity(GoalInfo),
> (
> Index: rbmm.actual_region_arguments.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.actual_region_arguments.m,v
> retrieving revision 1.3
> diff -u -r1.3 rbmm.actual_region_arguments.m
> --- rbmm.actual_region_arguments.m 23 Jul 2007 05:06:13 -0000 1.3
> +++ rbmm.actual_region_arguments.m 14 Aug 2007 23:41:11 -0000
> @@ -31,24 +31,28 @@
>
> :- import_module list.
> :- import_module map.
> -:- import_module pair.
>
> -:- type proc_pp_pair_region_list_table
> +:- type proc_pp_actual_region_args_table
> == map(
> pred_proc_id,
> - pp_pair_region_list_table
> + pp_actual_region_args_table
> ).
>
> -:- type pp_pair_region_list_table
> +:- type pp_actual_region_args_table
> == map(
> program_point,
> - pair(list(rptg_node), list(rptg_node))
> - % The first element is inputs, the second is outputs.
> + actual_region_args
> ).
>
> +:- type actual_region_args
> + ---> actual_region_args(
> + list(rptg_node), % constant (carried) region arguments.
> + list(rptg_node), % inputs (removed).
> + list(rptg_node) % outputs (created).
> + ).
> :- pred record_actual_region_arguments(module_info::in, rpta_info_table::in,
> proc_region_set_table::in, proc_region_set_table::in,
> - proc_region_set_table::in, proc_pp_pair_region_list_table::out) is det.
> + proc_region_set_table::in, proc_pp_actual_region_args_table::out) is det.
>
> %-----------------------------------------------------------------------------%
> %-----------------------------------------------------------------------------%
> @@ -75,8 +79,8 @@
> :- pred record_actual_region_arguments_pred(module_info::in,
> rpta_info_table::in, proc_region_set_table::in,
> proc_region_set_table::in, proc_region_set_table::in, pred_id::in,
> - proc_pp_pair_region_list_table::in, proc_pp_pair_region_list_table::out)
> - is det.
> + proc_pp_actual_region_args_table::in,
> + proc_pp_actual_region_args_table::out) is det.
>
> record_actual_region_arguments_pred(ModuleInfo, RptaInfoTable,
> ConstantRTable, DeadRTable, BornRTable, PredId,
> @@ -90,8 +94,8 @@
> :- pred record_actual_region_arguments_proc(module_info::in, pred_id::in,
> rpta_info_table::in, proc_region_set_table::in,
> proc_region_set_table::in, proc_region_set_table::in, proc_id::in,
> - proc_pp_pair_region_list_table::in, proc_pp_pair_region_list_table::out)
> - is det.
> + proc_pp_actual_region_args_table::in,
> + proc_pp_actual_region_args_table::out) is det.
>
> record_actual_region_arguments_proc(ModuleInfo, PredId, RptaInfoTable,
> ConstantRTable, DeadRTable, BornRTable, ProcId,
> @@ -112,7 +116,7 @@
> :- pred record_actual_region_arguments_goal(module_info::in,
> pred_proc_id::in, rpta_info_table::in, proc_region_set_table::in,
> proc_region_set_table::in, proc_region_set_table::in, hlds_goal::in,
> - pp_pair_region_list_table::in, pp_pair_region_list_table::out) is det.
> + pp_actual_region_args_table::in, pp_actual_region_args_table::out) is det.
>
> record_actual_region_arguments_goal(ModuleInfo, PPId, RptaInfoTable,
> ConstantRTable, DeadRTable, BornRTable, Goal,
> @@ -126,7 +130,7 @@
> hlds_goal_info::in, module_info::in, pred_proc_id::in,
> rpta_info_table::in, proc_region_set_table::in,
> proc_region_set_table::in, proc_region_set_table::in,
> - pp_pair_region_list_table::in, pp_pair_region_list_table::out) is det.
> + pp_actual_region_args_table::in, pp_actual_region_args_table::out) is det.
>
> record_actual_region_arguments_expr(conj(_, Conjs), _, ModuleInfo, PPId,
> RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
> @@ -192,7 +196,7 @@
> :- pred record_actual_region_arguments_case(module_info::in,
> pred_proc_id::in, rpta_info_table::in, proc_region_set_table::in,
> proc_region_set_table::in, proc_region_set_table::in, case::in,
> - pp_pair_region_list_table::in, pp_pair_region_list_table::out) is det.
> + pp_actual_region_args_table::in, pp_actual_region_args_table::out) is det.
>
> record_actual_region_arguments_case(ModuleInfo, PPId, RptaInfoTable,
> ConstantRTable, DeadRTable, BornRTable, Case, !ActualRegionArgProc) :-
> @@ -218,7 +222,7 @@
> program_point::in, pred_proc_id::in,
> rpta_info_table::in, proc_region_set_table::in,
> proc_region_set_table::in, proc_region_set_table::in,
> - pp_pair_region_list_table::in, pp_pair_region_list_table::out) is det.
> + pp_actual_region_args_table::in, pp_actual_region_args_table::out) is det.
>
> record_actual_region_arguments_call_site(CallerPPId, CallSite,
> CalleePPId, RptaInfoTable, ConstantRTable, DeadRTable,
> @@ -249,10 +253,9 @@
> LActualBornR0),
> list.reverse(LActualBornR0, LActualBornR),
>
> - % Record in two groups: input region arguments composed of constants and
> - % deads, and output ones which are borns.
> - Ins = LActualConstantR ++ LActualDeadR,
> - svmap.det_insert(CallSite, Ins - LActualBornR, !ActualRegionArgProc).
> + svmap.det_insert(CallSite,
> + actual_region_args(LActualConstantR, LActualDeadR, LActualBornR),
> + !ActualRegionArgProc).
>
> :- pred find_actual_param(map(rptg_node, rptg_node)::in, rptg_node::in,
> list(rptg_node)::in, list(rptg_node)::out) is det.
> Index: rbmm.interproc_region_lifetime.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.interproc_region_lifetime.m,v
> retrieving revision 1.3
> diff -u -r1.3 rbmm.interproc_region_lifetime.m
> --- rbmm.interproc_region_lifetime.m 23 Jul 2007 05:06:13 -0000 1.3
> +++ rbmm.interproc_region_lifetime.m 14 Aug 2007 23:41:11 -0000
> @@ -69,6 +69,7 @@
> :- import_module parse_tree.
> :- import_module parse_tree.mercury_to_mercury.
> :- import_module parse_tree.prog_data.
> +:- import_module parse_tree.prog_type.
> :- import_module transform_hlds.dependency_graph.
> :- import_module transform_hlds.rbmm.points_to_graph.
> :- import_module transform_hlds.smm_common.
> @@ -590,11 +591,7 @@
>
> retain_non_primitive_regions(ModuleInfo, Graph, Region, !RegionSet) :-
> NodeType = rptg_lookup_node_type(Graph, Region),
> - (
> - ( type_is_atomic(ModuleInfo, NodeType)
> - ; is_dummy_argument_type(ModuleInfo, NodeType)
> - )
> - ->
> + ( type_not_stored_in_region(NodeType, ModuleInfo) ->
> true
> ;
> svset.insert(Region, !RegionSet)
> Index: rbmm.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.m,v
> retrieving revision 1.6
> diff -u -r1.6 rbmm.m
> --- rbmm.m 20 Jul 2007 08:09:53 -0000 1.6
> +++ rbmm.m 14 Aug 2007 23:41:11 -0000
> @@ -25,6 +25,7 @@
> :- include_module points_to_analysis.
> :- include_module points_to_graph.
> :- include_module points_to_info.
> +:- include_module rbmm_goal_info_analysis.
> :- include_module region_instruction.
> :- include_module region_liveness_info.
> :- include_module region_resurrection_renaming.
> @@ -51,6 +52,7 @@
> :- import_module transform_hlds.rbmm.live_region_analysis.
> :- import_module transform_hlds.rbmm.live_variable_analysis.
> :- import_module transform_hlds.rbmm.points_to_analysis.
> +:- import_module transform_hlds.rbmm.rbmm_goal_info_analysis.
> :- import_module transform_hlds.rbmm.region_instruction.
> :- import_module transform_hlds.rbmm.region_resurrection_renaming.
> :- import_module transform_hlds.rbmm.region_transformation.
> @@ -115,8 +117,12 @@
> region_transform(RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
> ActualRegionArgumentTable, ResurRenamingTable, IteRenamingTable,
> RegionInstructionTable, ResurRenamingAnnoTable,
> - IteRenamingAnnoTable, map.init, _NameToVarTable, !ModuleInfo).
> + IteRenamingAnnoTable, map.init, NameToVarTable, !ModuleInfo),
> +
> + collect_rbmm_goal_info(RptaInfoTable, ActualRegionArgumentTable,
> + ResurRenamingTable, IteRenamingTable, NameToVarTable, !ModuleInfo).
>
> %-----------------------------------------------------------------------------%
> :- end_module transform_hlds.rbmm.
> %-----------------------------------------------------------------------------%
> +
> Index: rbmm.rbmm_goal_info_analysis.m
> ===================================================================
> RCS file: rbmm.rbmm_goal_info_analysis.m
> diff -N rbmm.rbmm_goal_info_analysis.m
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ rbmm.rbmm_goal_info_analysis.m 14 Aug 2007 23:41:11 -0000
> @@ -0,0 +1,488 @@
> +%-----------------------------------------------------------------------------%
> +% vim: ft=mercury ts=4 sw=4 et
> +%-----------------------------------------------------------------------------%
> +% Copyright (C) 2007 The University of Melbourne.
> +% This file may only be copied under the terms of the GNU General
> +% Public License - see the file COPYING in the Mercury distribution.
> +%-----------------------------------------------------------------------------%
> +%
> +% File rbmm.rbmm_goal_info_analysis.m.
> +% Main author: Quan Phan.
> +%
> +% This module fills in rbmm_goal_info field in hlds_goal_extra_info data
> +% structure. The details of this information can be read in hlds_goal.m.
> +%
> +% This information is used by the code generator to optimize the runtime
> +% support for region-based memory management.
> +%
> +%-----------------------------------------------------------------------------%
> +
> +:- module transform_hlds.rbmm.rbmm_goal_info_analysis.
> +:- interface.
> +
> +:- import_module hlds.
> +:- import_module hlds.hlds_module.
> +:- import_module transform_hlds.rbmm.actual_region_arguments.
> +:- import_module transform_hlds.rbmm.points_to_info.
> +:- import_module transform_hlds.rbmm.region_resurrection_renaming.
> +:- import_module transform_hlds.rbmm.region_transformation.
> +
> +:- pred collect_rbmm_goal_info(rpta_info_table::in,
> + proc_pp_actual_region_args_table::in, renaming_table::in,
> + renaming_table::in, name_to_prog_var_table::in,
> + module_info::in, module_info::out) is det.
> +
> +%-----------------------------------------------------------------------------%
> +%-----------------------------------------------------------------------------%
> +
> +:- implementation.
> +
> +:- import_module check_hlds.
> +:- import_module check_hlds.goal_path.
> +:- import_module check_hlds.type_util.
> +:- import_module hlds.hlds_goal.
> +:- import_module hlds.hlds_pred.
> +:- import_module libs.
> +:- import_module libs.compiler_util.
> +:- import_module mdbcomp.
> +:- import_module mdbcomp.prim_data.
> +:- import_module parse_tree.
> +:- import_module parse_tree.prog_data.
> +:- import_module parse_tree.prog_type.
> +:- import_module transform_hlds.rbmm.points_to_graph.
> +:- import_module transform_hlds.smm_common.
> +
> +:- import_module string.
> +:- import_module list.
> +:- import_module map.
> +:- import_module maybe.
> +:- import_module set.
> +
> +%-----------------------------------------------------------------------------%
> +%
> +% rbmm_goal_info analysis.
> +%
> +
> + % We need to collect this pieces of information for the procedures which
> + % have been region-analyzed. Therefore we can use one of the resulting
> + % tables from previous phases for the PPId. The use of
> + % ActualRegionArgumentTable here is convenient because we also need the
> + % information about actual region arguments in this analysis.
> + %
> +collect_rbmm_goal_info(RptaInfoTable, ActualRegionArgumentTable,
> + ResurRenamingTable, IteRenamingTable, NameToRegionVarTable,
> + !ModuleInfo) :-
> + map.foldl(collect_rbmm_goal_info_proc(RptaInfoTable, ResurRenamingTable,
> + IteRenamingTable, NameToRegionVarTable), ActualRegionArgumentTable,
> + !ModuleInfo).
> +
> +:- pred collect_rbmm_goal_info_proc(rpta_info_table::in,
> + renaming_table::in, renaming_table::in, name_to_prog_var_table::in,
> + pred_proc_id::in, pp_actual_region_args_table::in,
> + module_info::in, module_info::out) is det.
> +
> +collect_rbmm_goal_info_proc(RptaInfoTable, ResurRenamingTable,
> + IteRenamingTable, NameToRegionVarTable, PPId, ActualRegionsArgsProc,
> + !ModuleInfo) :-
> + module_info_pred_proc_info(!.ModuleInfo, PPId, PredInfo, ProcInfo0),
> + proc_info_get_goal(ProcInfo0, Body0),
> + map.lookup(RptaInfoTable, PPId, RptaInfo),
> + RptaInfo = rpta_info(Graph, _),
> + ( map.search(ResurRenamingTable, PPId, ResurRenamingProc0) ->
> + ResurRenamingProc = ResurRenamingProc0
> + ;
> + ResurRenamingProc = map.init
> + ),
> + ( map.search(IteRenamingTable, PPId, IteRenamingProc0) ->
> + IteRenamingProc = IteRenamingProc0
> + ;
> + IteRenamingProc = map.init
> + ),
> + map.lookup(NameToRegionVarTable, PPId, NameToRegionVarProc),
> + collect_rbmm_goal_info_goal(!.ModuleInfo, ProcInfo0, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, Body0, Body),
> + proc_info_set_goal(Body, ProcInfo0, ProcInfo),
> + module_info_set_pred_proc_info(PPId, PredInfo, ProcInfo, !ModuleInfo).
> +
> +:- pred collect_rbmm_goal_info_goal(module_info::in, proc_info::in,
> + rpt_graph::in, pp_actual_region_args_table::in, renaming_proc::in,
> + renaming_proc::in, name_to_prog_var::in,
> + hlds_goal::in, hlds_goal::out) is det.
> +
> +collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, !Goal) :-
> + !.Goal = hlds_goal(Expr0, Info0),
> + collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, Expr0, Expr, Info0, Info),
> + !:Goal = hlds_goal(Expr, Info).
> +
> +:- pred collect_rbmm_goal_info_goal_expr(module_info::in, proc_info::in,
> + rpt_graph::in, pp_actual_region_args_table::in, renaming_proc::in,
> + renaming_proc::in, name_to_prog_var::in,
> + hlds_goal_expr::in, hlds_goal_expr::out,
> + hlds_goal_info::in, hlds_goal_info::out) is det.
> +
> +collect_rbmm_goal_info_goal_expr(ModuleInfo, _, Graph, _, ResurRenamingProc,
> + IteRenamingProc, NameToRegionVar, !Expr, !Info) :-
> + !.Expr = unify(_, _, _, Unification, _),
> + ProgPoint = program_point_init(!.Info),
> + ( map.search(ResurRenamingProc, ProgPoint, ResurRenaming0) ->
> + ResurRenaming = ResurRenaming0
> + ;
> + ResurRenaming = map.init
> + ),
> + ( map.search(IteRenamingProc, ProgPoint, IteRenaming0) ->
> + IteRenaming = IteRenaming0
> + ;
> + IteRenaming = map.init
> + ),
> + collect_rbmm_goal_info_unification(Unification, ModuleInfo, Graph,
> + ResurRenaming, IteRenaming, NameToRegionVar, !Info).
> +
> +collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, _,
> + ActualRegionArgumentProc, _, _, _, !Expr, !Info) :-
> + !.Expr = plain_call(PredId, ProcId, Args, _, _, _),
> + CalleePPId = proc(PredId, ProcId),
> + (
> + is_create_region_call(!.Expr, ModuleInfo, CreatedRegion)
> + ->
> + RbmmGoalInfo = rbmm_goal_info(set.make_singleton_set(CreatedRegion),
> + set.init, set.init, set.init, set.init),
> + goal_info_set_maybe_rbmm(yes(RbmmGoalInfo), !Info)
> + ;
> + is_remove_region_call(!.Expr, ModuleInfo, RemovedRegion)
> + ->
> + RbmmGoalInfo = rbmm_goal_info(set.init,
> + set.make_singleton_set(RemovedRegion), set.init, set.init,
> + set.init),
> + goal_info_set_maybe_rbmm(yes(RbmmGoalInfo), !Info)
> + ;
> + some_are_special_preds([CalleePPId], ModuleInfo)
> + ->
> + goal_info_set_maybe_rbmm(yes(rbmm_info_init), !Info)
> + ;
> + CallSite = program_point_init(!.Info),
> + proc_info_get_vartypes(ProcInfo, VarTypes),
> + RegionArgs = list.filter(is_region_var(VarTypes), Args),
> + map.lookup(ActualRegionArgumentProc, CallSite, ActualRegionArgs),
> + ActualRegionArgs = actual_region_args(Constants, Inputs, _Outputs),
> + list.det_split_list(list.length(Constants), RegionArgs,
> + CarriedRegions, RemovedAndCreated),
> + list.det_split_list(list.length(Inputs), RemovedAndCreated,
> + RemovedRegions, CreatedRegions),
> + % XXX We safely approximate that RemovedRegions and CarriedRegions
> + % are allocated into and read from in this call.
> + AllocatedIntoAndReadFrom =
> + set.from_list(RemovedRegions ++ CarriedRegions),
> + RbmmGoalInfo = rbmm_goal_info(set.from_list(CreatedRegions),
> + set.from_list(RemovedRegions), set.from_list(CarriedRegions),
> + AllocatedIntoAndReadFrom, AllocatedIntoAndReadFrom),
> + goal_info_set_maybe_rbmm(yes(RbmmGoalInfo), !Info)
> + ).
> +
> + % We do not handle generic calls and calls to foreign procs in RBMM yet,
> + % so if a program has any of them the RBMM compilation will fail before
> + % reaching here. We just call sorry now so that they are not
> + % forgotten when we deal with these explicitly in the future.
> + %
> +collect_rbmm_goal_info_goal_expr(_, _, _, _, _, _, _, !Expr, !Info) :-
> + !.Expr = generic_call(_, _, _, _),
> + sorry(this_file,
> + "collect_rbmm_goal_info_goal_expr: generic call not handled").
> +collect_rbmm_goal_info_goal_expr(_, _, _, _, _, _, _, !Expr, !Info) :-
> + !.Expr = call_foreign_proc(_, _, _, _, _, _, _),
> + sorry(this_file,
> + "collect_rbmm_goal_info_goal_expr: call to foreign proc not handled").
> +
> +collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, !Expr, !Info) :-
> + !.Expr = conj(ConjType, Conjs0),
> + list.map(collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc), Conjs0, Conjs),
> + !:Expr = conj(ConjType, Conjs),
> +
> + % Calculate created, removed, allocated into, used regions.
> + compute_rbmm_info_conjunction(Conjs, rbmm_info_init, RbmmInfo0),
> +
> + % Calculate carried regions.
> + % The carried regions are those that are NOT removed, NOT created by all
> + % the conjuncts.
> + RbmmInfo0 = rbmm_goal_info(Created, Removed, _, AllocatedInto, Used),
> + NonLocals = goal_info_get_nonlocals(!.Info),
> + proc_info_get_vartypes(ProcInfo, VarTypes),
> + NonLocalRegions = set.filter(is_region_var(VarTypes), NonLocals),
> + set.difference(NonLocalRegions, set.union(Created, Removed), Carried),
> + RbmmInfo = rbmm_goal_info(Created, Removed, Carried, AllocatedInto, Used),
> + goal_info_set_maybe_rbmm(yes(RbmmInfo), !Info).
> +
> +collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, !Expr, !Info) :-
> + !.Expr = disj(Disjs0),
> + list.map(collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc), Disjs0, Disjs),
> + !:Expr = disj(Disjs),
> +
> + (
> + Disjs = [],
> + goal_info_set_maybe_rbmm(yes(rbmm_info_init), !Info)
> + ;
> + % Well-modedness requires that each disjunct creates, removes and
> + % carries the same regions, which are also created, removed, carried
> + % by the disjunction.
> + Disjs = [hlds_goal(_, DInfo) | _],
> + DRbmmInfo = goal_info_get_rbmm(DInfo),
> + DRbmmInfo = rbmm_goal_info(Created, Removed, Carried, _, _),
> + RbmmInfo0 = rbmm_goal_info(Created, Removed, Carried, set.init,
> + set.init),
> +
> + % Calculate allocated-into and used regions.
> + compute_rbmm_info_disjunction(Disjs, RbmmInfo0, RbmmInfo),
> + goal_info_set_maybe_rbmm(yes(RbmmInfo), !Info)
> + ).
> +
> +collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, !Expr, !Info) :-
> + !.Expr = switch(A, B, Cases0),
> + list.map(collect_rbmm_goal_info_case(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc), Cases0, Cases),
> + !:Expr = switch(A, B, Cases),
> + (
> + Cases = [],
> + unexpected(this_file, "collect_rbmm_goal_info_goal_expr: "
> + ++ "empty switch unexpected")
> + ;
> + % The process here is similar to that for nondet disjunction.
> + Cases = [Case | _],
> + Case = case(_, Goal),
> + Goal = hlds_goal(_, CaseInfo),
> + CaseRbmmInfo = goal_info_get_rbmm(CaseInfo),
> + CaseRbmmInfo = rbmm_goal_info(Created, Removed, Carried, _, _),
> + SwitchRbmmInfo0 = rbmm_goal_info(Created, Removed, Carried, set.init,
> + set.init),
> + compute_rbmm_info_switch(Cases, SwitchRbmmInfo0, SwitchRbmmInfo),
> + goal_info_set_maybe_rbmm(yes(SwitchRbmmInfo), !Info)
> + ).
> +
> +collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, !Expr, !Info) :-
> + !.Expr = negation(Goal0),
> + collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, Goal0, Goal),
> + !:Expr = negation(Goal),
> + Goal = hlds_goal(_, Info),
> + RbmmInfo = goal_info_get_rbmm(Info),
> + goal_info_set_maybe_rbmm(yes(RbmmInfo), !Info).
> +
> +collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, !Expr, !Info) :-
> + !.Expr = scope(Reason, Goal0),
> + collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, Goal0, Goal),
> + !:Expr = scope(Reason, Goal),
> + Goal = hlds_goal(_, Info),
> + RbmmInfo = goal_info_get_rbmm(Info),
> + goal_info_set_maybe_rbmm(yes(RbmmInfo), !Info).
> +
> +collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, !Expr, !Info) :-
> + !.Expr = if_then_else(A, Cond0, Then0, Else0),
> + collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, Cond0, Cond),
> + collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, Then0, Then),
> + collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, Else0, Else),
> + !:Expr = if_then_else(A, Cond, Then, Else),
> + Else = hlds_goal(_, ElseInfo),
> + RbmmInfo = goal_info_get_rbmm(ElseInfo),
> + goal_info_set_maybe_rbmm(yes(RbmmInfo), !Info).
> +
> +collect_rbmm_goal_info_goal_expr(_, _, _, _, _, _, _, !Expr, !Info) :-
> + !.Expr = shorthand(_),
> + unexpected(this_file,
> + "collect_rbmm_goal_info_goal_expr: shorthand unexpected").
> +
> + % The regions that are created inside this conjunction are all that are
> + % created inside each conjunct.
> + % The regions that are removed inside this conjunction are all that are
> + % removed inside each conjunct AND EXIST before the conjunction, i.e.,
> + % not being created in the condition.
> + % The regions that are allocated into inside this conjunction are those
> + % allocated into by any conjuncts AND EXIST ...
> + % The regions that are read from inside this conjunction are those that
> + % are read from by any conjuncts AND EXIST ...
> + %
> +:- pred compute_rbmm_info_conjunction(list(hlds_goal)::in,
> + rbmm_goal_info::in, rbmm_goal_info::out) is det.
> +
> +compute_rbmm_info_conjunction([], !RbmmInfo).
> +compute_rbmm_info_conjunction([Conj | Conjs], !RbmmInfo) :-
> + Conj = hlds_goal(_, CInfo),
> + CRbmmInfo = goal_info_get_rbmm(CInfo),
> + CRbmmInfo = rbmm_goal_info(CCreated, CRemoved, _, CAllocatedInto, CUsed),
> + !.RbmmInfo = rbmm_goal_info(Created0, Removed0, Carried, AllocatedInto0,
> + Used0),
> + set.union(CCreated, Created0, Created),
> + set.difference(set.union(CRemoved, Removed0), Created, Removed),
> + set.difference(set.union(CAllocatedInto, AllocatedInto0), Created,
> + AllocatedInto),
> + set.difference(set.union(CUsed, Used0), Created, Used),
> +
> + !:RbmmInfo = rbmm_goal_info(Created, Removed, Carried, AllocatedInto,
> + Used),
> + compute_rbmm_info_conjunction(Conjs, !RbmmInfo).
> +
> + % The regions that are allocated into inside this disjunction are those
> + % allocated into by any disjuncts AND EXIST ...
> + % The regions that are read from inside this disjunction are those that
> + % are read from by any disjuncts AND EXIST ...
> + %
> +:- pred compute_rbmm_info_disjunction(list(hlds_goal)::in,
> + rbmm_goal_info::in, rbmm_goal_info::out) is det.
> +
> +compute_rbmm_info_disjunction([], !RbmmInfo).
> +compute_rbmm_info_disjunction([Disj | Disjs], !RbmmInfo) :-
> + Disj = hlds_goal(_, DInfo),
> + DRbmmInfo = goal_info_get_rbmm(DInfo),
> + DRbmmInfo = rbmm_goal_info(_, _, _, DAllocatedInto, DUsed),
> + !.RbmmInfo = rbmm_goal_info(Created, Removed, Carried, AllocatedInto0,
> + Used0),
> + set.difference(set.union(DAllocatedInto, AllocatedInto0), Created,
> + AllocatedInto),
> + set.difference(set.union(DUsed, Used0), Created, Used),
> + !:RbmmInfo = rbmm_goal_info(Created, Removed, Carried, AllocatedInto,
> + Used),
> + compute_rbmm_info_disjunction(Disjs, !RbmmInfo).
> +
> + % The process here is similar to that for nondet disjunction.
> + %
> +:- pred compute_rbmm_info_switch(list(case)::in, rbmm_goal_info::in,
> + rbmm_goal_info::out) is det.
> +
> +compute_rbmm_info_switch([], !SwitchRbmmInfo).
> +compute_rbmm_info_switch([Case | Cases], !SwitchRbmmInfo) :-
> + Case = case(_, Goal),
> + Goal = hlds_goal(_, Info),
> + CaseRbmmInfo = goal_info_get_rbmm(Info),
> + CaseRbmmInfo = rbmm_goal_info(_, _, _, CaseAllocatedInto, CaseUsed),
> + !.SwitchRbmmInfo = rbmm_goal_info(Created, Removed, Carried,
> + AllocatedInto0, Used0),
> + set.difference(set.union(CaseAllocatedInto, AllocatedInto0), Created,
> + AllocatedInto),
> + set.difference(set.union(CaseUsed, Used0), Created, Used),
> + !:SwitchRbmmInfo = rbmm_goal_info(Created, Removed, Carried,
> + AllocatedInto, Used),
> + compute_rbmm_info_switch(Cases, !SwitchRbmmInfo).
> +
> +:- pred collect_rbmm_goal_info_unification(unification::in, module_info::in,
> + rpt_graph::in, renaming::in, renaming::in, name_to_prog_var::in,
> + hlds_goal_info::in, hlds_goal_info::out) is det.
> +
> +collect_rbmm_goal_info_unification(Unification, ModuleInfo, Graph,
> + ResurRenaming, IteRenaming, RegionNameToVar, !Info) :-
> + (
> + Unification = construct(_, _, _, _, HowToConstruct, _, _),
> + (
> + HowToConstruct = construct_in_region(AllocatedIntoRegion),
> + RbmmInfo = rbmm_goal_info(set.init, set.init,
> + set.make_singleton_set(AllocatedIntoRegion),
> + set.make_singleton_set(AllocatedIntoRegion), set.init),
> + goal_info_set_maybe_rbmm(yes(RbmmInfo), !Info)
> + ;
> + ( HowToConstruct = construct_statically(_)
> + ; HowToConstruct = construct_dynamically
> + ; HowToConstruct = reuse_cell(_)
> + ),
> + goal_info_set_maybe_rbmm(yes(rbmm_info_init), !Info)
> + )
> + ;
> + Unification = deconstruct(DeconsCellVar, _, _, _, _, _),
> + get_node_by_variable(Graph, DeconsCellVar, Node),
> + NodeType = rptg_lookup_node_type(Graph, Node),
> + ( if type_not_stored_in_region(NodeType, ModuleInfo)
> + then
> + goal_info_set_maybe_rbmm(yes(rbmm_info_init), !Info)
> + else
> + OriginalName = rptg_lookup_region_name(Graph, Node),
> + ( map.search(ResurRenaming, OriginalName, ResurName) ->
> + Name = ResurName
> + ; map.search(IteRenaming, OriginalName, IteName) ->
> + Name = IteName
> + ;
> + Name = OriginalName
> + ),
> + map.lookup(RegionNameToVar, Name, RegionVar),
> + RbmmInfo = rbmm_goal_info(set.init, set.init,
> + set.make_singleton_set(RegionVar),
> + set.init, set.make_singleton_set(RegionVar)),
> + goal_info_set_maybe_rbmm(yes(RbmmInfo), !Info)
> + )
> + ;
> + ( Unification = assign(_, _)
> + ; Unification = simple_test(_, _)
> + ),
> + goal_info_set_maybe_rbmm(yes(rbmm_goal_info(set.init, set.init,
> + set.init, set.init, set.init)), !Info)
> + ;
> + Unification = complicated_unify(_, _, _),
> + unexpected(this_file, "collect_rbmm_goal_info_unification:"
> + ++ " encounter complicated unification")
> + ).
> +
> +:- pred is_remove_region_call(hlds_goal_expr::in, module_info::in,
> + prog_var::out) is semidet.
> +
> +is_remove_region_call(plain_call(PredId, _ProcId, Args, _, _, _),
> + ModuleInfo, RemovedRegion) :-
> + module_info_pred_info(ModuleInfo, PredId, PredInfo),
> + pred_info_module(PredInfo) = mercury_region_builtin_module,
> + pred_info_name(PredInfo) = remove_region_pred_name,
> + Args = [RemovedRegion].
> +
> +:- pred is_create_region_call(hlds_goal_expr::in, module_info::in,
> + prog_var::out) is semidet.
> +
> +is_create_region_call(plain_call(PredId, _ProcId, Args, _, _, _),
> + ModuleInfo, CreatedRegion) :-
> + module_info_pred_info(ModuleInfo, PredId, PredInfo),
> + pred_info_module(PredInfo) = mercury_region_builtin_module,
> + pred_info_name(PredInfo) = create_region_pred_name,
> + Args = [CreatedRegion].
> +
> +:- pred collect_rbmm_goal_info_case(module_info::in, proc_info::in,
> + rpt_graph::in, pp_actual_region_args_table::in, renaming_proc::in,
> + renaming_proc::in, name_to_prog_var::in, case::in, case::out) is det.
> +
> +collect_rbmm_goal_info_case(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, !Case) :-
> + !.Case = case(Functor, Goal0),
> + collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
> + ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
> + NameToRegionVarProc, Goal0, Goal),
> + !:Case = case(Functor, Goal).
> +
> +%-----------------------------------------------------------------------------%
> +
> +:- func this_file = string.
> +
> +this_file = "rbmm.rbmm_goal_info_analysis.m".
> +
> +%-----------------------------------------------------------------------------%
> Index: rbmm.region_transformation.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.region_transformation.m,v
> retrieving revision 1.3
> diff -u -r1.3 rbmm.region_transformation.m
> --- rbmm.region_transformation.m 23 Jul 2007 05:06:15 -0000 1.3
> +++ rbmm.region_transformation.m 14 Aug 2007 23:41:11 -0000
> @@ -59,7 +59,7 @@
> %
> :- pred region_transform(rpta_info_table::in, proc_region_set_table::in,
> proc_region_set_table::in, proc_region_set_table::in,
> - proc_pp_pair_region_list_table::in,
> + proc_pp_actual_region_args_table::in,
> renaming_table::in, renaming_table::in, region_instruction_table::in,
> renaming_annotation_table::in, renaming_annotation_table::in,
> name_to_prog_var_table::in, name_to_prog_var_table::out,
> @@ -174,7 +174,7 @@
> %
> :- pred region_transform_pred(rpta_info_table::in, proc_region_set_table::in,
> proc_region_set_table::in, proc_region_set_table::in,
> - proc_pp_pair_region_list_table::in,
> + proc_pp_actual_region_args_table::in,
> renaming_table::in, renaming_table::in, region_instruction_table::in,
> renaming_annotation_table::in, renaming_annotation_table::in,
> pred_id::in, name_to_prog_var_table::in, name_to_prog_var_table::out,
> @@ -208,7 +208,7 @@
> %
> :- pred region_transform_proc(rpta_info_table::in, proc_region_set_table::in,
> proc_region_set_table::in, proc_region_set_table::in,
> - proc_pp_pair_region_list_table::in,
> + proc_pp_actual_region_args_table::in,
> renaming_table::in, renaming_table::in, region_instruction_table::in,
> renaming_annotation_table::in, renaming_annotation_table::in,
> pred_id::in, proc_id::in, name_to_prog_var_table::in,
> @@ -268,7 +268,7 @@
> %
> :- pred annotate_proc(module_info::in, pred_info::in, rpt_graph::in,
> region_set::in, region_set::in, region_set::in,
> - pp_pair_region_list_table::in, renaming_proc::in, renaming_proc::in,
> + pp_actual_region_args_table::in, renaming_proc::in, renaming_proc::in,
> region_instruction_proc::in, renaming_annotation_proc::in,
> renaming_annotation_proc::in, prog_varset::in, prog_varset::out,
> vartypes::in, vartypes::out, list(prog_var)::in, list(prog_var)::out,
> @@ -348,7 +348,7 @@
> % caused by renaming and annotations needed for resurrection problem.
> %
> :- pred region_transform_goal(module_info::in, rpt_graph::in,
> - renaming_proc::in, renaming_proc::in, pp_pair_region_list_table::in,
> + renaming_proc::in, renaming_proc::in, pp_actual_region_args_table::in,
> region_instruction_proc::in, renaming_annotation_proc::in,
> renaming_annotation_proc::in, hlds_goal::in, hlds_goal::out,
> name_to_prog_var::in, name_to_prog_var::out,
> @@ -415,7 +415,7 @@
> ).
>
> :- pred region_transform_goal_expr(module_info::in, rpt_graph::in,
> - renaming::in, renaming::in, pp_pair_region_list_table::in,
> + renaming::in, renaming::in, pp_actual_region_args_table::in,
> program_point::in, hlds_goal_expr::in, hlds_goal_expr::out,
> hlds_goal_info::in, hlds_goal_info::out, name_to_prog_var::in,
> name_to_prog_var::out, prog_varset::in, prog_varset::out,
> @@ -433,10 +433,10 @@
> ( map.search(ActualRegionArgProc, ProgPoint, ActualNodes0) ->
> ActualNodes = ActualNodes0
> ;
> - ActualNodes = pair([],[])
> + ActualNodes = actual_region_args([], [], [])
> ),
> - ActualNodes = Ins - Outs,
> - AllNodes = Ins ++ Outs,
> + ActualNodes = actual_region_args(Constants, Ins, Outs),
> + AllNodes = Constants ++ Ins ++ Outs,
> list.map_foldl3(
> node_to_var_with_both_renamings(Graph, ResurRenaming, IteRenaming),
> AllNodes, ActualRegionArgs, !NameToVar, !VarSet, !VarTypes),
> @@ -488,7 +488,7 @@
> % Because an atomic goal is turned into a conjunction, we need to
> % flatten its compounding conjunction if it is in one.
> :- pred region_transform_compound_goal(module_info::in, rpt_graph::in,
> - renaming_proc::in, renaming_proc::in, pp_pair_region_list_table::in,
> + renaming_proc::in, renaming_proc::in, pp_actual_region_args_table::in,
> region_instruction_proc::in, renaming_annotation_proc::in,
> renaming_annotation_proc::in, hlds_goal::in, hlds_goal::out,
> name_to_prog_var::in, name_to_prog_var::out,
> @@ -584,11 +584,7 @@
> IsUnique, SubInfo),
> get_node_by_variable(Graph, Var, Node),
> NodeType = rptg_lookup_node_type(Graph, Node),
> - (
> - ( type_is_atomic(ModuleInfo, NodeType)
> - ; is_dummy_argument_type(ModuleInfo, NodeType)
> - )
> - ->
> + ( type_not_stored_in_region(NodeType, ModuleInfo) ->
> true
> ;
> Name = rptg_lookup_region_name(Graph, Node),
> @@ -623,7 +619,7 @@
> % Finally, we try to flatten this new conjunction.
> %
> :- pred region_transform_case(module_info::in, rpt_graph::in,
> - renaming_proc::in, renaming_proc::in, pp_pair_region_list_table::in,
> + renaming_proc::in, renaming_proc::in, pp_actual_region_args_table::in,
> region_instruction_proc::in, renaming_annotation_proc::in,
> renaming_annotation_proc::in, hlds_goal::in, case::in, case::out,
> name_to_prog_var::in, name_to_prog_var::out,
> Index: type_util.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/compiler/type_util.m,v
> retrieving revision 1.179
> diff -u -r1.179 type_util.m
> --- type_util.m 9 Aug 2007 05:28:26 -0000 1.179
> +++ type_util.m 14 Aug 2007 23:41:12 -0000
> @@ -233,6 +233,11 @@
> %
> :- func cons_id_adjusted_arity(module_info, mer_type, cons_id) = int.
>
> + % Check if (the terms of) the type is NOT allocated in a region in
> + % region-based memory management.
> + %
> +:- pred type_not_stored_in_region(mer_type::in, module_info::in) is semidet.
> +
> %-----------------------------------------------------------------------------%
>
> % If possible, get the argument types for the cons_id. We need to pass in
> @@ -955,6 +960,16 @@
>
> %-----------------------------------------------------------------------------%
>
> +type_not_stored_in_region(Type, ModuleInfo) :-
> + ( type_is_atomic(ModuleInfo, Type)
> + ; is_dummy_argument_type(ModuleInfo, Type)
> + ; Type = type_info_type
> + ; Type = type_ctor_info_type
> + ; type_is_var(Type)
> + ).
> +
> +%-----------------------------------------------------------------------------%
> +
> maybe_get_cons_id_arg_types(ModuleInfo, MaybeType, ConsId0, Arity,
> MaybeTypes) :-
> ( ConsId0 = cons(_SymName, _) ->
> Index: user_guide.texi
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/doc/user_guide.texi,v
> retrieving revision 1.540
> diff -u -r1.540 user_guide.texi
> --- user_guide.texi 13 Aug 2007 03:01:55 -0000 1.540
> +++ user_guide.texi 14 Aug 2007 23:42:53 -0000
> @@ -6771,6 +6771,7 @@
> b - builtin flags on calls,
> c - contexts of goals and types,
> d - determinism of goals,
> +e - created, removed, carried, allocated into, and used regions,
> f - follow_vars sets of goals,
> g - goal feature lists,
> i - variables whose instantiation changes,
> @@ -6792,7 +6793,8 @@
> I - imported predicates,
> M - mode and inst information,
> P - path information,
> -S - information about structure sharing
> +R - live forward use, live backward use and reuse possibilities,
> +S - information about structure sharing,
> T - type and typeclass information,
> U - unify and compare predicates,
> Z - information about globals structs representing call and answer tables.
> cvs diff: Diffing notes
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list