[m-rev.] for review: [CTGC] indirect reuse analysis.

Julien Fischer juliensf at cs.mu.OZ.AU
Wed May 24 13:29:32 AEST 2006


On Thu, 18 May 2006, Nancy Mazur wrote:

> Estimated hours taken: 10
> Branches: main
>
> Provide the indirect reuse analysis part of the CTGC system. Using a fixpoint
> computation, this propagates the reuse conditions determined by the direct
> reuse analysis step through procedure calls.
>
> compiler/ctgc.datastruct.m:
> 	Minor additions.
>
> compiler/ctgc.livedata.m:
> 	(new file) Types and operations needed for defining the lattice of
> 	possibly live datastructures.
>
> compiler/ctgc.m:
> 	Add livedata submodule.
>
> compiler/ctgc.util.m:
> 	Provide the operations for determining variable and type renamings,
> 	used both by the structure sharing analysis as well as the reuse
> 	analysis.
>
> compiler/hlds_module.m:
> 	Add structure reuse information to collect the mapping between
> 	procedures, and their reuse versions.
>
> compiler/prog_data.m:
> 	New types "dead_vars", "live_vars".
>
> compiler/structure_reuse.analysis.m:
> 	Add the indirect reuse analysis step.
>
> compiler/structure_reuse.direct.detect_garbage.m:
> compiler/structure_sharing.domain.m:
> 	Mainly moving the operation of looking up sharing information and
> 	combining it with existing sharing to a more appropriate place, namely
> 	structure_sharing.domain.m
>
> compiler/structure_reuse.domain.m:
> 	Add a renaming operation but especially two predicates needed to
> 	verify whether a given procedure call satisfies the derived reuse
> 	conditions, and to translate these reuse conditions to the
> 	head variables of the procedure in which the procedure call occurs.
>
> compiler/structure_reuse.indirect.m:
> 	The actual indirect reuse analysis.
>
> compiler/structure_reuse.m:
> 	Add "structure_reuse.indirect" as a submodule.
>
> compiler/structure_sharing.analysis.m:
> 	small changes.
>
> Index: compiler/ctgc.datastruct.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/ctgc.datastruct.m,v
> retrieving revision 1.6
> diff -u -d -r1.6 ctgc.datastruct.m
> --- compiler/ctgc.datastruct.m	10 May 2006 10:56:49 -0000	1.6
> +++ compiler/ctgc.datastruct.m	18 May 2006 12:01:04 -0000
> @@ -35,6 +35,11 @@
>      %
>  :- pred datastruct_equal(datastruct::in, datastruct::in) is semidet.
>
> +    % Verify whether the datastructure represents a top cell, ie. where

s/ie./i.e./

> +    % the selector path is an empty path.
> +    %
> +:- pred datastruct_refers_to_topcell(datastruct::in) is semidet.
> +
>      % Select a subterm of the given datastructure using the specified selector.
>      % It is assumed that the selector is a valid selector for that
>      % datastructure.

...

> Index: compiler/ctgc.livedata.m
> ===================================================================
> RCS file: compiler/ctgc.livedata.m
> diff -N compiler/ctgc.livedata.m
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ compiler/ctgc.livedata.m	18 May 2006 12:01:05 -0000
> @@ -0,0 +1,292 @@
> +%-----------------------------------------------------------------------------%
> +% vim: ft=mercury ts=4 sw=4 et
> +%-----------------------------------------------------------------------------%
> +% Copyright (C) 2006 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: ctgc.livedata.m.
> +% Main author: nancy.
> +%
> +% Definition of the live_data type used to represent the set of datastructures
> +% that are probably (not definitely!) live at a given program point (goal).
> +% A data structure is said to be "live" if the memory used to represent
> +% that data structure may possibly be accessed during the further execution
> +% of the program w.r.t. the program point (goal) looked at.
> +%
> +%-----------------------------------------------------------------------------%
> +
> +:- module transform_hlds.ctgc.livedata.
> +:- interface.
> +
> +:- import_module parse_tree.prog_data.
> +:- import_module hlds.hlds_module.
> +:- import_module hlds.hlds_pred.
> +:- import_module transform_hlds.ctgc.structure_sharing.
> +:- import_module transform_hlds.ctgc.structure_sharing.domain.
> +:- import_module hlds.hlds_goal.
> +
> +:- import_module list.
> +
> +%-----------------------------------------------------------------------------%
> +
> +:- type livedata.
> +
> +    % Create an initial set of live data structure, possibly given a list
> +    % of live variables or data structures.
> +    %
> +:- func livedata_init = livedata.   % Which assumes that nothing is live.
> +:- func livedata_init_from_vars(live_vars) = livedata.
> +:- func livedata_init_from_datastructs(live_datastructs) = livedata.
> +:- func livedata_init_as_top = livedata.
> +
> +    % Verify whether the liveness set is bottom resp. top.
> +:- pred livedata_is_bottom(livedata::in) is semidet.
> +:- pred livedata_is_top(livedata::in) is semidet.
> +
> +    % Return the list of live data structures represented by livedata.
> +    % Returns a software error when the livedata set is top.
> +    %
> +:- func livedata_get_datastructs(livedata) = list(datastruct).
> +
> +    % Least upper bound of all the livedata.
> +    %
> +:- func livedata_least_upper_bound(module_info, proc_info, livedata,
> +    livedata) = livedata.
> +:- func livedata_least_upper_bound_list(module_info, proc_info,
> +    list(livedata)) = livedata.
> +
> +    % Subsumption predicates.
> +    %
> +:- pred livedata_subsumes_prog_var(livedata::in, prog_var::in) is semidet.
> +:- pred livedata_subsumes_datastruct(module_info::in, proc_info::in,
> +    livedata::in, datastruct::in) is semidet.
> +
> +    % Projection operation.
> +    %
> +:- func livedata_project(list(prog_var), livedata) = livedata.
> +
> +%-----------------------------------------------------------------------------%
> +
> +:- func livedata_init_at_goal(module_info, proc_info, hlds_goal_info,
> +    sharing_as) = livedata.
> +:- func livedata_add_liveness(module_info, proc_info, live_datastructs,
> +    sharing_as, livedata) = livedata.
> +
> +:- pred nodes_are_not_live(module_info::in, proc_info::in,
> +    list(datastruct)::in, livedata::in) is semidet.
> +%-----------------------------------------------------------------------------%
> +
> +:- implementation.
> +
> +:- import_module libs.compiler_util.
> +:- import_module transform_hlds.ctgc.datastruct.
> +
> +:- import_module set.
> +
> +
> +:- type livedata
> +    --->    bottom      % There are no live data structures.
> +    ;       top         % All data structures may be live.
> +    ;       live(list(datastruct)).
> +                        % Only the listed datastructures can possibly
> +                        % be live.

There are already types with constructors called bottom and top in several parts
of the compiler.  It would probably a good idea to use more distinct names,
e.g.

	:- type livedata
		--->	livedata_bottom
		;	livedata_top
		;	livedata_live(list(datastruct)).

(It's probably worth doing a bit of renaming along similar lines in
other parts of the CTGC system as well).

...

> +livedata_project(ProgVars, LiveData) = ProjectedLiveData :-
> +    (
> +        LiveData = bottom,
> +        ProjectedLiveData = bottom
> +    ;
> +        LiveData = top,
> +        ProjectedLiveData = top
> +    ;
> +        LiveData = live(Data),
> +        list.filter(list_contains_datastruct_var(ProgVars),
> +            Data, FilteredData),
> +        ( FilteredData = [] -> ProjectedLiveData = bottom
> +        ;  ProjectedLiveData = live(FilteredData)
> +        )

That if-then-else can be a switch.

...

> Index: compiler/ctgc.util.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/ctgc.util.m,v
> retrieving revision 1.5
> diff -u -d -r1.5 ctgc.util.m
> --- compiler/ctgc.util.m	10 May 2006 10:56:49 -0000	1.5
> +++ compiler/ctgc.util.m	18 May 2006 12:01:05 -0000
> @@ -18,8 +18,10 @@
>
>  :- import_module hlds.hlds_module.
>  :- import_module hlds.hlds_pred.
> +:- import_module parse_tree.prog_data.
>
>  :- import_module list.
> +:- import_module map.
>
>  %-----------------------------------------------------------------------------%
>
> @@ -34,16 +36,32 @@
>  :- pred pred_requires_no_analysis(module_info::in, pred_id::in) is semidet.
>  :- pred pred_requires_analysis(module_info::in, pred_id::in) is semidet.
>
> +    % Given the pred_proc_id of a procedure call and its actual arguments,
> +    % determine the variable renaming to rename anything which is defined
> +    % in terms of the formal arguments of the called procedure to the context
> +    % of the actual arguments.
> +    %
> +:- func get_variable_renaming(module_info, pred_proc_id, prog_vars) =
> +    map(prog_var, prog_var).
> +

The module goal_util defines the type prog_var_renaming (==map(prog_var,
prog_var)).

...

> Index: compiler/hlds_module.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/hlds_module.m,v
> retrieving revision 1.134
> diff -u -d -r1.134 hlds_module.m
> --- compiler/hlds_module.m	29 Mar 2006 08:06:48 -0000	1.134
> +++ compiler/hlds_module.m	18 May 2006 12:01:07 -0000
> @@ -185,6 +185,14 @@
>      ;       complexity_input_fixed_size
>      ;       complexity_output.
>
> +        % This type is used to record the mapping between original
> +        % procedures, and their optimised versions with respect to
> +        % structure reuse (CTGC).
> +        %
> +:- type structure_reuse_info
> +    --->    structure_reuse_info(
> +                map(pred_proc_id, pair(pred_proc_id, sym_name))
> +            ).

...

> Index: compiler/structure_reuse.direct.detect_garbage.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/structure_reuse.direct.detect_garbage.m,v
> retrieving revision 1.1
> diff -u -d -r1.1 structure_reuse.direct.detect_garbage.m
> --- compiler/structure_reuse.direct.detect_garbage.m	10 May 2006 10:56:56 -0000	1.1
> +++ compiler/structure_reuse.direct.detect_garbage.m	18 May 2006 12:01:12 -0000
> @@ -90,6 +90,7 @@
>                  func(C) = G :- (G = C ^ case_goal), Cases), !SharingAs,
>              !DeadCellTable)
>      ;
> +        % XXX

Why has that XXX comment been added there?

>          GoalExpr = not(_Goal)
>      ;
>          GoalExpr = scope(_, SubGoal),
> @@ -208,28 +209,6 @@
>
>  var_is_live(Var, LiveData) :-
>      list.member(datastruct_init(Var), LiveData).

...

> +    % reuse_as_rename_using_module_info(ModuleInfo, PPId,
> +    %   ActualVars, ActualTypes, ActualTVarset, FormalReuse, ActualReuse):
> +    %
> +    % Renaming of the formal description of structure reuse conditions to the
> +    % actual description of these conditions. The information about the formal
> +    % variables needs to be extracted from the module information.
> +    % A list of variables and types is used as the actual variables and types.
> +    % The type variables set in the actual context must also be specified.
> +    %

I don't understand the last part of that description.

> +:- pred reuse_as_rename_using_module_info(module_info::in,
> +    pred_proc_id::in, prog_vars::in, list(mer_type)::in, tvarset::in,
> +    reuse_as::in, reuse_as::out) is det.
> +
>      % Given a variable and type variable mapping, rename the reuses
>      % conditions accordingly.

...

> +:- func reuse_condition_from_called_proc_to_local_condition(module_info,
> +    proc_info, prog_vars, live_datastructs, sharing_as, reuse_condition) =
> +    reuse_condition.
> +
> +reuse_condition_from_called_proc_to_local_condition(ModuleInfo, ProcInfo,
> +        HeadVars, LuData, SharingAs, CalledCondition) = LocalCondition :-
> +    (
> +        CalledCondition = always, % should not occur though...
> +        LocalCondition = always

If it shouldn't occur then why not call unexpected/2 here?

> +    ;
> +        CalledCondition = condition(CalledDeadNodes,
> +            CalledInUseNodes, CalledSharingAs),
> +
> +        % Translate the dead nodes:
> +        AllDeadNodes = extend_datastructs(ModuleInfo, ProcInfo,
> +            SharingAs, CalledDeadNodes),
> +        AllDeadHeadVarNodes = datastructs_project(HeadVars, AllDeadNodes),
> +
> +        (
> +            AllDeadHeadVarNodes = []
> +        ->
> +            LocalCondition = always
> +        ;
> +            % Translate the in use nodes:
> +            AllInUseNodes = extend_datastructs(ModuleInfo, ProcInfo,
> +                SharingAs, list.append(LuData, CalledInUseNodes)),
> +            AllInUseHeadVarNodes = datastructs_project(HeadVars,
> +                AllInUseNodes),
> +
> +            % Translate the sharing information:
> +            AllLocalSharing = sharing_as_comb(ModuleInfo, ProcInfo,
> +                CalledSharingAs, SharingAs),
> +            AllHeadVarLocalSharing = sharing_as_project(HeadVars,
> +                AllLocalSharing),
> +
> +            LocalCondition = condition(AllDeadHeadVarNodes,
> +                AllInUseHeadVarNodes, AllHeadVarLocalSharing)
> +        )

You can turn that if-then-else into a switch.

...

> Index: compiler/structure_reuse.indirect.m
> ===================================================================
> RCS file: compiler/structure_reuse.indirect.m
> diff -N compiler/structure_reuse.indirect.m
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ compiler/structure_reuse.indirect.m	18 May 2006 12:01:14 -0000
> @@ -0,0 +1,676 @@
> +%------------------------------------------------------------------------------%
> +% vim: ft=mercury ff=unix ts=4 sw=4 et
> +%-----------------------------------------------------------------------------%
> +% Copyright (C) 2006 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: structure_reuse.indirect.m
> +% Main authors: nancy
> +%
> +% Determine the indirect reuse. This requires a fixpoint computation.
> +%------------------------------------------------------------------------------%
> +
> +:- module structure_reuse.indirect.
> +
> +:- interface.
> +
> +:- import_module hlds.hlds_module.
> +:- import_module transform_hlds.ctgc.structure_reuse.domain.
> +:- import_module transform_hlds.ctgc.structure_sharing.domain.
> +
> +:- import_module io.
> +
> +    % Direct reuse analysis derives information about deconstructions that
> +    % under certain circumstances (formalised as "reuse conditions") form
> +    % the last ever (memory) access to the deconstructed term.
> +    %
> +    % Indirect reuse analysis is about verifying procedure calls to see
> +    % whether these procedure calls satisfy these reuse conditions for
> +    % direct reuse, and under what circumstances (again expressed as
> +    % reuse conditions). Using a fixpoint computation, we determine the
> +    % overall reuse conditions for a procedure call to be replaced by a
> +    % call to an optimised version of that procedure w.r.t. its memory usage.
> +    %
> +    % The results of the analysis are primarely stored in the reuse table, yet

s/primarely/primarily/

> +    % also involves annotations at the level of the individual procedure calls,
> +    % which explains the need for updating the HLDS as well.
> +    %
> +:- pred indirect_reuse_pass(sharing_as_table::in, module_info::in,
> +    module_info::out, reuse_as_table::in, reuse_as_table::out,
> +    io::di, io::uo) is det.
> +

...

> +indirect_reuse_pass(SharingTable, !ModuleInfo, !ReuseTable, !IO):-
> +    %
> +    % Perform a bottom-up traversal of the SCCs in the program,

s/program/module/

> +    % analysing indirect structure reuse in each one as we go.
> +    %
> +    module_info_ensure_dependency_info(!ModuleInfo),
> +    module_info_get_maybe_dependency_info(!.ModuleInfo, MaybeDepInfo),
> +    (
> +        MaybeDepInfo = yes(DepInfo),
> +        hlds_dependency_info_get_dependency_ordering(DepInfo, SCCs),
> +        list.foldl3(indirect_reuse_analyse_scc(SharingTable),
> +            SCCs, !ModuleInfo, !ReuseTable, !IO)
> +    ;
> +        MaybeDepInfo = no,
> +        unexpected(this_file, "No dependency information.")
> +    ).
> +
> +:- pred indirect_reuse_analyse_scc(sharing_as_table::in,
> +    list(pred_proc_id)::in, module_info::in, module_info::out,
> +    reuse_as_table::in, reuse_as_table::out, io::di, io::uo) is det.
> +
> +indirect_reuse_analyse_scc(SharingTable, SCC, !ModuleInfo, !ReuseTable, !IO) :-
> +    ( preds_requiring_no_analysis(!.ModuleInfo, SCC) ->
> +        true
> +    ;
> +        indirect_reuse_analyse_scc_until_fixpoint(SharingTable,
> +            SCC, !.ReuseTable, !ModuleInfo,
> +            sr_fixpoint_table_init(SCC, !.ReuseTable), FixpointTable, !IO),
> +        list.foldl(update_reuse_in_table(FixpointTable), SCC, !ReuseTable)
> +    ).
> +
> +:- pred indirect_reuse_analyse_scc_until_fixpoint(sharing_as_table::in,
> +    list(pred_proc_id)::in, reuse_as_table::in,
> +    module_info::in, module_info::out, sr_fixpoint_table::in,
> +    sr_fixpoint_table::out, io::di, io::uo) is det.
> +
> +indirect_reuse_analyse_scc_until_fixpoint(SharingTable, SCC,
> +        ReuseTable, !ModuleInfo, !FixpointTable, !IO):-
> +    list.foldl3(indirect_reuse_analyse_pred_proc(SharingTable, ReuseTable),
> +        SCC, !ModuleInfo, !FixpointTable, !IO),
> +    ( sr_fixpoint_table_stable(!.FixpointTable) ->
> +        true
> +    ;
> +        sr_fixpoint_table_new_run(!FixpointTable),
> +        indirect_reuse_analyse_scc_until_fixpoint(SharingTable,
> +            SCC, ReuseTable, !ModuleInfo, !FixpointTable, !IO)
> +    ).
> +

...

> +
> +    % The type ir_background_info has the purpose to collect all the necessary
> +    % background information needed to be able to perform the indirect reuse
> +    % (ir) analysis of a specific procedure.
> +    %
> +:- type ir_background_info
> +    --->    ir_background_info(
> +                module_info     :: module_info,
> +                pred_info       :: pred_info,
> +                proc_info       :: proc_info,
> +                sharing_table   :: sharing_as_table,
> +                reuse_table     :: reuse_as_table,
> +                headvars        :: list(prog_var)
> +            ).
> +
> +    % The type analysis_info gathers the analysis information that may change
> +    % from goal to goal.
> +    %
> +:- type analysis_info
> +    --->    analysis_info(
> +                sharing_as      :: sharing_as,
> +                reuse_as        :: reuse_as,
> +                static_vars     :: set(prog_var),
> +                fptable         :: sr_fixpoint_table
> +            ).
> +

analysis_info is not a good name  for this as it's also the name of one of
the principle data structures used by the intermodule-analysis framework
(which we will eventually be using here.)

...

> +%-----------------------------------------------------------------------------%
> +
> +:- pred indirect_reuse_analyse_goal(ir_background_info::in, hlds_goal::in,
> +    hlds_goal::out, analysis_info::in, analysis_info::out,
> +    io::di, io::uo) is det.
> +
> +indirect_reuse_analyse_goal(BaseInfo, !Goal, !AnalysisInfo, !IO) :-
> +    !.Goal = GoalExpr0 - GoalInfo0,
> +    (
> +        GoalExpr0 = conj(ConjType, Goals0),
> +        list.map_foldl2(indirect_reuse_analyse_goal(BaseInfo), Goals0,
> +            Goals, !AnalysisInfo, !IO),
> +        GoalExpr = conj(ConjType, Goals),
> +        !:Goal = GoalExpr - GoalInfo0
> +    ;
> +        GoalExpr0 = call(CalleePredId, CalleeProcId, CalleeArgs, _, _, _),
> +        verify_indirect_reuse(BaseInfo, CalleePredId, CalleeProcId,
> +            CalleeArgs, GoalInfo0, GoalInfo, !AnalysisInfo, !IO),
> +        lookup_sharing_and_comb(BaseInfo ^ module_info, BaseInfo ^ proc_info,
> +            BaseInfo ^ sharing_table, CalleePredId, CalleeProcId,
> +            CalleeArgs, !.AnalysisInfo ^ sharing_as, NewSharing),
> +        !:AnalysisInfo = !.AnalysisInfo ^ sharing_as := NewSharing,
> +        GoalExpr = GoalExpr0,
> +        !:Goal = GoalExpr - GoalInfo
> +    ;
> +        GoalExpr0 = generic_call(_GenDetails, _, _, _),
> +        goal_info_get_context(GoalInfo0, Context),
> +        context_to_string(Context, ContextString),
> +        !:AnalysisInfo = !.AnalysisInfo ^ sharing_as :=
> +            sharing_as_top_sharing_accumulate("generic call ("
> +                ++ ContextString ++ ")",
> +            !.AnalysisInfo ^ sharing_as)
> +    ;
> +        GoalExpr0 = unify(_, _, _, Unification, _),
> +        % Record the statically constructed variables:
> +        ( Unification = construct(Var, _, _, _,
> +                construct_statically(_), _, _) ->
> +            !:AnalysisInfo = !.AnalysisInfo ^ static_vars :=
> +                set.insert(!.AnalysisInfo ^ static_vars, Var)
> +        ;
> +            true
> +        ),
> +        !:AnalysisInfo = !.AnalysisInfo ^ sharing_as :=
> +            add_unify_sharing(BaseInfo ^ module_info, BaseInfo ^ proc_info,
> +                Unification, GoalInfo0, !.AnalysisInfo ^ sharing_as)
> +    ;
> +        GoalExpr0 = disj(Goals0),
> +        list.map2_foldl2(
> +            indirect_reuse_analyse_disj(BaseInfo, !.AnalysisInfo),
> +            Goals0, Goals, AnalysisInfoList, !.AnalysisInfo ^ fptable,
> +            NewFixpointTable, !IO),
> +        analysis_info_combine(BaseInfo, AnalysisInfoList, NewFixpointTable,
> +            !AnalysisInfo),
> +        GoalExpr = disj(Goals),
> +        !:Goal = GoalExpr - GoalInfo0
> +    ;
> +        GoalExpr0 = switch(A, B, Cases0),
> +        list.map2_foldl2(
> +            indirect_reuse_analyse_case(BaseInfo, !.AnalysisInfo),
> +            Cases0, Cases, AnalysisInfoList, !.AnalysisInfo ^ fptable,
> +            NewFixpointTable, !IO),
> +        analysis_info_combine(BaseInfo, AnalysisInfoList, NewFixpointTable,
> +            !AnalysisInfo),
> +        GoalExpr = switch(A, B, Cases),
> +        !:Goal = GoalExpr - GoalInfo0
> +    ;
> +        % XXX

A little more information please.

...

> +    % Verify whether the caller's environment satisfies the reuse conditions
> +    % stated in the reuse description of the called procedure. If this
> +    % succeeds, then translate those reuse conditions to this caller's
> +    % environment.
> +    %
> +    % Pre-conditions: The sharing is not top, and reuse_as contains at least
> +    % one conditional reuse condition.
> +    %
> +:- pred verify_indirect_reuse_2(ir_background_info::in, analysis_info::in,
> +    hlds_goal_info::in, pred_proc_id::in, list(prog_var)::in, reuse_as::in,
> +    reuse_as::out) is det.
> +
> +verify_indirect_reuse_2(BaseInfo, AnalysisInfo, GoalInfo, CalleePPId,
> +        CalleeArgs, FormalReuseAs, NewReuseAs):-
> +    ModuleInfo = BaseInfo ^ module_info,
> +    PredInfo = BaseInfo ^ pred_info,
> +    ProcInfo = BaseInfo ^ proc_info,
> +    SharingAs = AnalysisInfo ^ sharing_as,
> +    proc_info_get_vartypes(ProcInfo, ActualVarTypes),
> +    pred_info_get_typevarset(PredInfo, ActualTVarset),
> +    list.map(map.lookup(ActualVarTypes), CalleeArgs, CalleeTypes),
> +    reuse_as_rename_using_module_info(ModuleInfo, CalleePPId,
> +        CalleeArgs, CalleeTypes, ActualTVarset, FormalReuseAs, ActualReuseAs),
> +    LiveData = livedata_init_at_goal(ModuleInfo, ProcInfo, GoalInfo,
> +        SharingAs),
> +    ProjectedLiveData = livedata_project(CalleeArgs, LiveData),
> +    (
> +        % Given the preconditions, livedata wil not be empty, and

s/wil/will/

I suggest adding a sanity checking that verifys those preconditions.

> +        % reuse_as contains at least one reuse condition.
> +        reuse_as_satisfied(ModuleInfo, ProcInfo, ProjectedLiveData,
> +            SharingAs, set.to_sorted_list(AnalysisInfo ^ static_vars),
> +            ActualReuseAs)
> +    ->
> +        LuData = list.map(datastruct_init,
> +            set.to_sorted_list(set.union(goal_info_get_lfu(GoalInfo),
> +                goal_info_get_lbu(GoalInfo)))),
> +        NewReuseAs = reuse_as_from_called_procedure_to_local_reuse_as(
> +            ModuleInfo, ProcInfo, BaseInfo ^ headvars, LuData, SharingAs,
> +            ActualReuseAs)
> +    ;
> +        NewReuseAs = reuse_as_init  % no reuse
> +    ).
> +

...

> Index: compiler/structure_sharing.domain.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/structure_sharing.domain.m,v
> retrieving revision 1.8
> diff -u -d -r1.8 structure_sharing.domain.m
> --- compiler/structure_sharing.domain.m	10 May 2006 10:56:57 -0000	1.8
> +++ compiler/structure_sharing.domain.m	18 May 2006 12:01:17 -0000
> @@ -87,7 +87,7 @@
>
>      % Return a short description of the sharing information.
>      %
> -:- func short_description(sharing_as) = string.
> +:- func sharing_as_short_description(sharing_as) = string.
>
>      % Projection operation.
>      % This operation reduces the sharing information to information
> @@ -98,6 +98,7 @@
>      %
>  :- pred sharing_as_project(prog_vars::in,
>      sharing_as::in, sharing_as::out) is det.
> +:- func sharing_as_project(prog_vars, sharing_as) = sharing_as.
>  :- pred sharing_as_project_set(set(prog_var)::in,
>      sharing_as::in, sharing_as::out) is det.
>
> @@ -113,10 +114,11 @@
>      %   ActualVars, ActualTypes, ActualTVarset, FormalSharing, ActualSharing):
>      %
>      % Renaming of the formal description of data structure sharing to the
> -    % actual description of the sharing. The formal information is given
> -    % using the module information. A list of variables and types is used as
> -    % the actual variables and types.
> -    % recorded in the module info.
> +    % actual description of the sharing. The information about the formal
> +    % variables needs to be extracted from the module information.
> +    % A list of variables and types is used as the actual variables and types.
> +    % The type variables set in the actual context must also be specified.
> +    %
>      %
>  :- pred sharing_as_rename_using_module_info(module_info::in,
>      pred_proc_id::in, prog_vars::in, list(mer_type)::in, tvarset::in,
> @@ -175,6 +177,8 @@
>      %
>  :- func extend_datastruct(module_info, proc_info, sharing_as, datastruct)
>      = list(datastruct).
> +:- func extend_datastructs(module_info, proc_info, sharing_as,
> +    list(datastruct)) = list(datastruct).
>
>      % apply_widening(ModuleInfo, ProcInfo, WideningLimit, WideningDone,
>      %   SharingIn, SharingOut):
> @@ -230,6 +234,15 @@
>
>  %-----------------------------------------------------------------------------%
>
> +    % Lookup the sharing information of a called procedure (given its
> +    % pred_id and proc_id), and combine it with the already existing

s/already/any/?

> +    % sharing information.
> +    %
> +:- pred lookup_sharing_and_comb(module_info::in, proc_info::in,
> +    sharing_as_table::in, pred_id::in, proc_id::in, prog_vars::in,
> +    sharing_as::in, sharing_as::out) is det.

Julien.
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list