[m-rev.] for post-commit review: goal ids
Paul Bone
pbone at csse.unimelb.edu.au
Mon Jan 3 16:05:20 AEDT 2011
On Mon, Dec 20, 2010 at 06:46:07PM +1100, Zoltan Somogyi wrote:
> For review by anyone. I don't particularly care whether it makes it to
> the release branch or not.
>
> Zoltan.
>
> The existing representation of goal_paths is suboptimal for several reasons.
>
> - Sometimes we need forward goal paths (e.g. to look up goals), and sometimes
> we need reverse goal paths (e.g. when computing goal paths in the first
> place). We had two types for them, but
>
> - their names, goal_path and goal_path_consable, were not expressive, and
> - we could store only one of them in goal_infos.
>
> - Testing whether goal A is a subgoal of goal B is quite error-prone using
> either form of goal paths.
>
> - Using a goal path as a key in a map, which several compiler passes want to
> do, requires lots of expensive comparisons.
>
> This diff replaces most uses of goal paths with goal ids. A goal id is an
> integer, so it can be used as a key in faster maps, or even in arrays.
> Every goal in the body of a procedure gets its id allocated in a depth first
> search. Since we process each goal before we dive into is descendants,
> the goal representing the whole body of a procedure always gets goal id 0.
> The depth first traversal also builds up a map (the containing goal map)
> that tells us the parent goal of ever subgoal, with the obvious exception
s/ever/every/
> of the root goal itself. From the containing goal map, one can compute
> both reverse and forward goal paths. It can also serve as the basis of an
> efficient test of whether the goal identified by goal id A is an ancestor
> of another goal identified by goal id B. We don't yet use this test,
> but I expect we will in the future.
>
> mdbcomp/program_representation.m:
> Add the goal_id type.
>
> Replace the existing goal_path and goal_path_consable types
> with two new types, forward_goal_path and reverse_goal_path.
> Since these now have wrappers around the list of goal path steps
> that identify each kind of goal path, it is now ok to expose their
> representations. This makes several compiler passes easier to code.
>
> Update the set of operations on goal paths to work on the new data
> structures.
>
> Add a couple of step types to represent lambdas and try goals.
> Their omission prior to this would have been a bug for constraint-based
> mode analysis, or any other compiler pass prior to the expansion out
> of lambda and try goals that wanted to use goal paths to identify
> subgoals.
ITYM
...expanding out...
> browser/declarative_tree.m:
> mdbcomp/rtti_access.m:
> mdbcomp/slice_and_dice.m:
> mdbcomp/trace_counts.m:
> slice/mcov.m:
> deep_profiler/*.m:
> Conform to the changes in goal path representation.
>
> compiler/hlds_goal:
> Replace the goal_path field with a goal_id field in the goal_info,
> indicating that from now on, this should be used to identify goals.
>
> Keep a reverse_goal_path field in the goal_info for use by RBMM and
> CTGC. Those analyses were too hard to convert to using goal_ids,
> especially since RBMM uses goal_paths to identify goals in multi-pass
> algorithms that should be one-pass and should not NEED to identify
> any goals for later processing.
This file and some others are missing their .m suffix.
> compiler/goal_path:
> Add predicates to fill in goal_ids, and update the predicates
> filling in the now deprecated reverse goal path fields.
>
> Add the operations needed by the rest of the compiler
> on goal ids and containing goal maps.
>
> Remove the option to set goal paths using "mode equivalent steps".
> Constraint based mode analysis now uses goal ids, and can now
> do its own equivalent optimization quite simply.
>
> Move the goal_path module from the check_hlds package to the hlds
> package.
>
> compiler/*.m:
> Conform to the changes in goal path representation.
>
> Most modules now use goal_ids to identify goals, and use a containing
> goal map to convert the goal ids to goal paths when needed.
> However, the ctgc and rbmm modules still use (reverse) goal paths.
>
> library/digraph.m:
> library/group.m:
> library/injection.m:
> library/pprint.m:
> library/pretty_printer.m:
> library/term_to_xml.m:
> Minor style improvements.
> Index: compiler/call_gen.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/compiler/call_gen.m,v
> retrieving revision 1.197
> diff -u -r1.197 call_gen.m
> --- compiler/call_gen.m 15 Dec 2010 06:29:29 -0000 1.197
> +++ compiler/call_gen.m 15 Dec 2010 06:33:13 -0000
> @@ -65,6 +65,7 @@
>
> :- import_module backend_libs.builtin_ops.
> :- import_module hlds.arg_info.
> +:- import_module hlds.goal_path.
> :- import_module hlds.hlds_llds.
> :- import_module hlds.hlds_module.
> :- import_module hlds.instmap.
> @@ -106,11 +107,20 @@
> get_next_label(ReturnLabel, !CI),
> call_gen.call_comment(!.CI, PredId, CodeModel, CallComment),
> Context = goal_info_get_context(GoalInfo),
> - GoalPath = goal_info_get_goal_path(GoalInfo),
> + GoalId = goal_info_get_goal_id(GoalInfo),
> + get_containing_goal_map(!.CI, MaybeContainingGoalMap),
> + (
> + MaybeContainingGoalMap = yes(ContainingGoalMap),
> + GoalPath = goal_id_to_forward_path(ContainingGoalMap, GoalId),
> + MaybeGoalPath = yes(GoalPath)
> + ;
> + MaybeContainingGoalMap = no,
> + MaybeGoalPath = no
> + ),
> CallCode = from_list([
> llds_instr(livevals(LiveVals), ""),
> llds_instr(llcall(Address, code_label(ReturnLabel), ReturnLiveLvalues,
> - Context, GoalPath, CallModel), CallComment),
> + Context, MaybeGoalPath, CallModel), CallComment),
> llds_instr(label(ReturnLabel), "continuation label")
> ]),
>
> @@ -132,7 +142,7 @@
> goal_info_has_feature(GoalInfo, feature_debug_tail_rec_call),
> MaybeTraceInfo = yes(TraceInfo)
> ->
> - generate_tailrec_event_code(TraceInfo, ArgsInfos, GoalPath, Context,
> + generate_tailrec_event_code(TraceInfo, ArgsInfos, GoalId, Context,
> TraceTailRecResetAndEventCode, TailRecLabel, !CI),
> JumpCode = from_list([
> llds_instr(livevals(LiveVals), ""),
> @@ -227,7 +237,7 @@
> % Make the call.
> get_next_label(ReturnLabel, !CI),
> Context = goal_info_get_context(GoalInfo),
> - GoalPath = goal_info_get_goal_path(GoalInfo),
> + GoalId = goal_info_get_goal_id(GoalInfo),
>
> % Figure out what variables will be live at the return point, and where,
> % for use in the accurate garbage collector, and in the debugger.
> @@ -239,10 +249,19 @@
> handle_return(OutArgsInfos, GoalInfo, NonLiveOutputs,
> ReturnInstMap, ReturnLiveLvalues, !CI),
>
> + get_containing_goal_map(!.CI, MaybeContainingGoalMap),
> + (
> + MaybeContainingGoalMap = yes(ContainingGoalMap),
> + GoalPath = goal_id_to_forward_path(ContainingGoalMap, GoalId),
> + MaybeGoalPath = yes(GoalPath)
> + ;
> + MaybeContainingGoalMap = no,
> + MaybeGoalPath = no
> + ),
> CallCode = from_list([
> llds_instr(livevals(LiveVals), ""),
> llds_instr(llcall(CodeAddr, code_label(ReturnLabel), ReturnLiveLvalues,
> - Context, GoalPath, CallModel), "Setup and call"),
> + Context, MaybeGoalPath, CallModel), "Setup and call"),
> llds_instr(label(ReturnLabel), "Continuation label")
> ]),
>
In what cases will !.CI not have a containing goal map?
Is it bad if llds_instr is not provided a goal path?
If so, how wasy is it to remove the maybe wrappers here and keep the code
deterministic?
>
> -:- pred mode_equiv_step(goal_path_step::in) is semidet.
> +:- pred fill_conj_id_slots(slot_info::in, goal_id::in, int::in,
> + int::in, int::out, containing_goal_map::in, containing_goal_map::out,
> + list(hlds_goal)::in, list(hlds_goal)::out) is det.
>
> -mode_equiv_step(Step) :-
> - ( Step = step_disj(_)
> - ; Step = step_neg
> - ; Step = step_scope(_)
> - ; Step = step_ite_else
> - ).
> +fill_conj_id_slots(_, _, _, !GoalNum, !ContainingGoalMap, [], []).
> +fill_conj_id_slots(SlotInfo, GoalId, N0, !GoalNum, !ContainingGoalMap,
> + [Goal0 | Goals0], [Goal | Goals]) :-
> + N1 = N0 + 1,
> + ContainingGoal = containing_goal(GoalId, step_conj(N1)),
> + fill_goal_id_slots(SlotInfo, ContainingGoal, !GoalNum, !ContainingGoalMap,
> + Goal0, Goal),
> + fill_conj_id_slots(SlotInfo, GoalId, N1, !GoalNum, !ContainingGoalMap,
> + Goals0, Goals).
> +
Is it clearer to make the step step_conj(N0) rather than N1, and call this
predicate with 1 for the parameter N0?
This could just be a subjective thing.
> Index: compiler/proc_gen.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/compiler/proc_gen.m,v
> retrieving revision 1.40
> diff -u -r1.40 proc_gen.m
> --- compiler/proc_gen.m 15 Dec 2010 06:29:56 -0000 1.40
> +++ compiler/proc_gen.m 15 Dec 2010 06:33:23 -0000
> @@ -300,11 +301,23 @@
> %---------------------------------------------------------------------------%
>
> generate_proc_code(PredInfo, ProcInfo0, PredId, ProcId, ModuleInfo0,
> - !GlobalData, Proc) :-
> + !GlobalData, CProc) :-
> % The modified module_info and proc_info are both discarded
> % on return from generate_proc_code.
> maybe_set_trace_level(PredInfo, ModuleInfo0, ModuleInfo),
> - ensure_all_headvars_are_named(ProcInfo0, ProcInfo),
> + ensure_all_headvars_are_named(ProcInfo0, ProcInfo1),
> +
> + % We use the globals from the original module info, so that
> + module_info_get_globals(ModuleInfo0, Globals0),
> + globals.get_trace_level(Globals0, TraceLevel0),
> + ( given_trace_level_is_none(TraceLevel0) = no ->
> + fill_goal_id_slots_in_proc(ModuleInfo, ContainingGoalMap,
> + ProcInfo1, ProcInfo),
> + MaybeContainingGoalMap = yes(ContainingGoalMap)
> + ;
> + MaybeContainingGoalMap = no,
> + ProcInfo = ProcInfo1
> + ),
The comment above trails off.
> Index: compiler/smm_common.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/compiler/smm_common.m,v
> retrieving revision 1.6
> diff -u -r1.6 smm_common.m
> --- compiler/smm_common.m 4 Sep 2008 11:41:01 -0000 1.6
> +++ compiler/smm_common.m 9 Dec 2010 05:19:28 -0000
> %
> -% Definition of a program point
> +% Definition of a program point.
> %
> -
> - % A program point records the place at which a data structure possibly
> - % becomes garbage.
> - %
> -:- type program_point
> - ---> pp(
> - pp_context :: term.context,
> - pp_path :: goal_path
> +
> + % A program point identifies a place at which a data structure possibly
> + % becomes garbage.
> + %
> +:- type program_point
> + ---> pp(
> + pp_context :: term.context,
> + pp_id :: reverse_goal_path
> ).
Shound the field name still be pp_path if this is a goal path rather
than a goal id?
> Index: deep_profiler/coverage.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/coverage.m,v
> retrieving revision 1.10
> diff -u -r1.10 coverage.m
> --- deep_profiler/coverage.m 15 Dec 2010 06:30:33 -0000 1.10
> +++ deep_profiler/coverage.m 17 Dec 2010 02:41:26 -0000
> @@ -431,19 +440,20 @@
> % conjunction. Each goal also has it's own coverage.
> %
> :- pred conj_annotate_coverage_2(coverage_reference_info::in,
> - goal_path::in, int::in, coverage_before::in, coverage_after::out,
> + list(goal_path_step)::in, int::in,
> + coverage_before::in, coverage_after::out,
> list(goal_rep(unit))::in, list(goal_rep(coverage_info))::out) is det.
>
We shoult make the list of goal path steps here an actual goal_path
type since this type is no-longer abstract. This is also true for a
number of places below.
> Index: deep_profiler/display_report.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/display_report.m,v
> retrieving revision 1.32
> diff -u -r1.32 display_report.m
> --- deep_profiler/display_report.m 15 Dec 2010 06:30:33 -0000 1.32
> +++ deep_profiler/display_report.m 17 Dec 2010 03:03:39 -0000
> @@ -2212,8 +2212,8 @@
> :- pred format_coverage_point_row(coverage_point::in, table_row::out) is det.
>
> format_coverage_point_row(CoveragePoint, Row) :-
> - CoveragePoint = coverage_point(Count, GoalPath, CPType),
> - GoalPathString = goal_path_to_string(GoalPath),
> + CoveragePoint = coverage_point(Count, RevGoalPath, CPType),
> + GoalPathString = rev_goal_path_to_string(RevGoalPath),
> GoalPathCell = table_cell(td_s(GoalPathString)),
> TypeCell = table_cell(td_s(string(CPType))),
> CountCell = table_cell(td_i(Count)),
> @@ -4272,10 +4272,10 @@
> CallSiteDesc = call_site_desc(CSSPtr, _ContainerPSPtr,
> _FileName, _LineNumber, _ModuleName,
> _UnQualRefinedName, _QualRefinedName,
> - SlotNumber, GoalPath, _MaybeCallee),
> + SlotNumber, RevGoalPath, _MaybeCallee),
> RefinedName = call_site_desc_get_caller_refined_id(MaybeCurModuleName,
> ModuleQual, CallSiteDesc),
> - GoalPathStr = goal_path_to_string(GoalPath),
> + GoalPathStr = rev_goal_path_to_string(RevGoalPath),
> string.format("%s @ %s #%d",
> [s(RefinedName), s(GoalPathStr), i(SlotNumber)], Name),
> Cmd = deep_cmd_dump_call_site_static(CSSPtr),
For printing reports we should probably print goal paths in forward
order. That is the path from the root to the goal in question.
> Index: deep_profiler/dump.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/dump.m,v
> retrieving revision 1.20
> diff -u -r1.20 dump.m
> --- deep_profiler/dump.m 15 Dec 2010 06:30:33 -0000 1.20
> +++ deep_profiler/dump.m 17 Dec 2010 02:42:32 -0000
> @@ -620,8 +620,8 @@
>
> :- pred format_cp_info(int::in, coverage_point_info::in, string::out) is det.
>
> -format_cp_info(Num, coverage_point_info(Path, CPType), String) :-
> - goal_path_to_string(Path) = PathString,
> +format_cp_info(Num, coverage_point_info(RevPath, CPType), String) :-
> + rev_goal_path_to_string(RevPath) = PathString,
> format("coverage_point[%d]: %s, %s",
> [i(Num), s(string(CPType)), s(PathString)], String).
As above.
> Index: deep_profiler/mdprof_fb.automatic_parallelism.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/mdprof_fb.automatic_parallelism.m,v
> retrieving revision 1.22
> diff -u -r1.22 mdprof_fb.automatic_parallelism.m
> --- deep_profiler/mdprof_fb.automatic_parallelism.m 15 Dec 2010 06:30:33 -0000 1.22
> +++ deep_profiler/mdprof_fb.automatic_parallelism.m 17 Dec 2010 04:04:22 -0000
> @@ -480,10 +481,12 @@
> Length = list.foldl((func(seq_conj(ConjsI), Acc) = Acc + length(ConjsI)),
> Conj ^ cpc_conjs, 0),
> (
> - GoalPath \= ConjGoalPath,
> - goal_path_inside(ConjGoalPath, GoalPath, RelativePath),
> - goal_path_consable(RelativePath, RelativePathCons),
> - goal_path_consable_remove_first(RelativePathCons, Step, _),
> + % XXX zs: I am not confident of the update for goal path
> + % representations.
> + RevGoalPath \= RevConjGoalPath,
> + rev_goal_path_inside(RevConjGoalPath, RevGoalPath, RevRelativePath),
> + RevRelativePath = rgp(RevRelativePathSteps),
> + list.last(RevRelativePathSteps, Step),
> Step = step_conj(ConjNum),
> ConjNum > FirstConjunct,
> ConjNum =< FirstConjunct + Length
This is correct. The XXX can be removed.
Everything else is fine, Thanks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.mercurylang.org/archives/reviews/attachments/20110103/2759c5ff/attachment.sig>
More information about the reviews
mailing list