[m-rev.] diff: enable more meaningful experimentation with inlining
Zoltan Somogyi
zs at cs.mu.OZ.AU
Mon Sep 12 18:31:12 AEST 2005
Enable more meaningful experimentation with inlining parameters. We haven't
changed the defaults since 1996, and I want to experiment to find out what
the new defaults should be.
compiler/options.m:
Add a new option, --inline-call-cost, that gives the assumed cost of
a call.
compiler/hlds_pred.m:
Have separate markers for inlining requested by the user versus
inlining proposed by the compiler itself.
compiler/inlining.m:
When calculating the size increase from a proposed inlining operation,
subtract the assumed size cost of the call from the size cost of the
inlined predicate.
Always respect user-requested inline markers, even if doing so would
breach the number-of-vars threshold. That threshold is not very
relevant now; it was set before tree234.m maintained balanced trees!
Rename apart two predicates that differed only in arity.
compiler/add_pragma.m:
compiler/add_pred.m:
compiler/hlds_out.m:
compiler/intermod.m:
compiler/table_gen.m:
Conform to the new set of markers.
Zoltan.
cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/add_pragma.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/add_pragma.m,v
retrieving revision 1.8
diff -u -b -r1.8 add_pragma.m
--- compiler/add_pragma.m 12 Sep 2005 05:24:02 -0000 1.8
+++ compiler/add_pragma.m 12 Sep 2005 07:07:29 -0000
@@ -193,11 +193,11 @@
;
Pragma = inline(Name, Arity),
add_pred_marker("inline", Name, Arity, ImportStatus, Context,
- inline, [no_inline], !ModuleInfo, !IO)
+ user_marked_inline, [user_marked_no_inline], !ModuleInfo, !IO)
;
Pragma = no_inline(Name, Arity),
add_pred_marker("no_inline", Name, Arity, ImportStatus, Context,
- no_inline, [inline], !ModuleInfo, !IO)
+ user_marked_no_inline, [user_marked_inline], !ModuleInfo, !IO)
;
Pragma = obsolete(Name, Arity),
add_pred_marker("obsolete", Name, Arity, ImportStatus,
@@ -333,7 +333,8 @@
% which would invalidate the instmap_deltas that the mode_check_clauses
% feature prevents the recomputation of.
add_pred_marker("mode_check_clauses", Name, Arity, ImportStatus,
- Context, no_inline, [inline], !ModuleInfo, !IO)
+ Context, user_marked_no_inline, [user_marked_inline], !ModuleInfo,
+ !IO)
).
add_pragma_export(Origin, Name, PredOrFunc, Modes, C_Function, Context,
@@ -1499,7 +1500,10 @@
% declaration. Tabled procedures cannot be inlined.
pred_info_get_markers(PredInfo0, Markers),
globals.io_lookup_bool_option(warn_table_with_inline, WarnInline, !IO),
- ( check_marker(Markers, inline), WarnInline = yes ->
+ (
+ check_marker(Markers, user_marked_inline),
+ WarnInline = yes
+ ->
TablePragmaStr = string.format("`:- pragma %s'", [s(EvalMethodStr)]),
InlineWarning = [
words("Warning: "), simple_call_id(PredOrFunc - PredName/Arity),
@@ -1855,7 +1859,7 @@
% So we must disable inlining for fact_table procedures.
%
add_pred_marker("fact_table", SymName, Arity, Status, Context,
- no_inline, [], !ModuleInfo, !IO).
+ user_marked_no_inline, [], !ModuleInfo, !IO).
% Create a list(pragma_var) that looks like the ones that are created
% for foreign_proc in prog_io.m.
Index: compiler/add_pred.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/add_pred.m,v
retrieving revision 1.3
diff -u -b -r1.3 add_pred.m
--- compiler/add_pred.m 12 Sep 2005 05:24:02 -0000 1.3
+++ compiler/add_pred.m 12 Sep 2005 07:07:30 -0000
@@ -271,7 +271,7 @@
% inline code for calls to these predicates.
%
pred_info_get_markers(!.PredInfo, Markers0),
- add_marker(no_inline, Markers0, Markers),
+ add_marker(user_marked_no_inline, Markers0, Markers),
pred_info_set_markers(Markers, !PredInfo).
%-----------------------------------------------------------------------------%
Index: compiler/hlds_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_out.m,v
retrieving revision 1.366
diff -u -b -r1.366 hlds_out.m
--- compiler/hlds_out.m 12 Sep 2005 05:24:07 -0000 1.366
+++ compiler/hlds_out.m 12 Sep 2005 07:07:30 -0000
@@ -1074,8 +1074,9 @@
hlds_out__marker_name(stub, "stub").
hlds_out__marker_name(infer_type, "infer_type").
hlds_out__marker_name(infer_modes, "infer_modes").
-hlds_out__marker_name(inline, "inline").
-hlds_out__marker_name(no_inline, "no_inline").
+hlds_out__marker_name(user_marked_inline, "inline").
+hlds_out__marker_name(user_marked_no_inline, "no_inline").
+hlds_out__marker_name(heuristic_inline, "heuristic_inline").
hlds_out__marker_name(dnf, "dnf").
hlds_out__marker_name(obsolete, "obsolete").
hlds_out__marker_name(class_method, "class_method").
Index: compiler/hlds_pred.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_pred.m,v
retrieving revision 1.176
diff -u -b -r1.176 hlds_pred.m
--- compiler/hlds_pred.m 12 Sep 2005 05:24:08 -0000 1.176
+++ compiler/hlds_pred.m 12 Sep 2005 07:07:31 -0000
@@ -1154,12 +1154,22 @@
; obsolete % Requests warnings if this predicate is used.
% Used for pragma(obsolete).
- ; inline % Requests that this predicate be inlined.
+
+ ; user_marked_inline
+ % The user requests that this be predicate should
+ % be inlined, even if it exceeds the usual size limits.
% Used for pragma(inline).
+ % Mutually exclusive with user_marked_no_inline.
- ; no_inline % Requests that this be predicate not be inlined.
- % Used for pragma(no_inline). Conflicts with `inline'
- % marker.
+ ; user_marked_no_inline
+ % The user requests that this be predicate should
+ % not be inlined. Used for pragma(no_inline).
+ % Mutually exclusive with user_marked_inline.
+
+ ; heuristic_inline
+ % The compiler (meaning probably inlining.m) requests
+ % that this predicate be inlined. Does not override
+ % user_marked_no_inline.
% The default flags for Aditi predicates are
% aditi, dnf, supp_magic, psn and memo.
@@ -2262,11 +2272,15 @@
pred_info_requested_inlining(PredInfo0) :-
pred_info_get_markers(PredInfo0, Markers),
- check_marker(Markers, inline).
+ (
+ check_marker(Markers, user_marked_inline)
+ ;
+ check_marker(Markers, heuristic_inline)
+ ).
pred_info_requested_no_inlining(PredInfo0) :-
pred_info_get_markers(PredInfo0, Markers),
- check_marker(Markers, no_inline).
+ check_marker(Markers, user_marked_no_inline).
pred_info_get_purity(PredInfo0, Purity) :-
pred_info_get_markers(PredInfo0, Markers),
Index: compiler/inlining.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/inlining.m,v
retrieving revision 1.126
diff -u -b -r1.126 inlining.m
--- compiler/inlining.m 12 Sep 2005 05:24:09 -0000 1.126
+++ compiler/inlining.m 12 Sep 2005 07:07:31 -0000
@@ -184,7 +184,8 @@
---> params(
simple :: bool,
single_use :: bool,
- size_threshold :: int,
+ call_cost :: int,
+ compound_size_threshold :: int,
simple_goal_threshold :: int,
var_threshold :: int,
highlevel_code :: bool,
@@ -209,6 +210,7 @@
globals__io_get_globals(Globals, !IO),
globals__lookup_bool_option(Globals, inline_simple, Simple),
globals__lookup_bool_option(Globals, inline_single_use, SingleUse),
+ globals__lookup_int_option(Globals, inline_call_cost, CallCost),
globals__lookup_int_option(Globals, inline_compound_threshold,
CompoundThreshold),
globals__lookup_int_option(Globals, inline_simple_threshold,
@@ -217,7 +219,7 @@
globals__lookup_bool_option(Globals, highlevel_code, HighLevelCode),
globals__io_get_trace_level(TraceLevel, !IO),
AnyTracing = bool__not(given_trace_level_is_none(TraceLevel)),
- Params = params(Simple, SingleUse, CompoundThreshold,
+ Params = params(Simple, SingleUse, CallCost, CompoundThreshold,
SimpleThreshold, VarThreshold, HighLevelCode, AnyTracing),
%
@@ -279,7 +281,8 @@
(
Simple = Params ^ simple,
SingleUse = Params ^ single_use,
- CompoundThreshold = Params ^ size_threshold,
+ CallCost = Params ^ call_cost,
+ CompoundThreshold = Params ^ compound_size_threshold,
SimpleThreshold = Params ^ simple_goal_threshold,
PredProcId = proc(PredId, ProcId),
module_info_pred_info(ModuleInfo, PredId, PredInfo),
@@ -297,7 +300,11 @@
map__search(NeededMap, Entity, Needed),
Needed = yes(NumUses),
goal_size(CalledGoal, Size),
- Size * NumUses =< CompoundThreshold
+ % The size increase due to inlining at a call site is not Size,
+ % but the difference between Size and the size of the call.
+ % CallCost is the user-provided approximation of the size of the
+ % call.
+ (Size - CallCost) * NumUses =< CompoundThreshold
;
SingleUse = yes,
map__search(NeededMap, Entity, Needed),
@@ -602,23 +609,27 @@
VarSet0, VarTypes0, TypeVarSet0, RttiVarMaps0,
_DidInlining0, Requantify0, DetChanged0, PurityChanged0),
+ module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
+ PredInfo, ProcInfo),
% Should we inline this call?
(
inlining__should_inline_proc(PredId, ProcId, Builtin, HighLevelCode,
- AnyTracing, InlinedProcs, Markers, ModuleInfo),
-
+ AnyTracing, InlinedProcs, Markers, ModuleInfo, UserReq),
+ (
+ UserReq = yes
+ ;
+ UserReq = no,
% Okay, but will we exceed the number-of-variables threshold?
varset__vars(VarSet0, ListOfVars),
list__length(ListOfVars, ThisMany),
% We need to find out how many variables the Callee has.
- module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
- PredInfo, ProcInfo),
proc_info_varset(ProcInfo, CalleeVarSet),
varset__vars(CalleeVarSet, CalleeListOfVars),
list__length(CalleeListOfVars, CalleeThisMany),
TotalVars = ThisMany + CalleeThisMany,
TotalVars =< VarThresh
+ )
->
inlining__do_inline_call(HeadTypeParams, ArgVars, PredInfo, ProcInfo,
VarSet0, VarSet, VarTypes0, VarTypes, TypeVarSet0, TypeVarSet,
@@ -835,34 +846,41 @@
%
:- pred inlining__should_inline_proc(pred_id::in, proc_id::in,
builtin_state::in, bool::in, bool::in, set(pred_proc_id)::in,
- pred_markers::in, module_info::in) is semidet.
+ pred_markers::in, module_info::in, bool::out) is semidet.
inlining__should_inline_proc(PredId, ProcId, BuiltinState, HighLevelCode,
- _Tracing, InlinedProcs, CallingPredMarkers, ModuleInfo) :-
+ _Tracing, InlinedProcs, CallingPredMarkers, ModuleInfo, UserReq) :-
InlinePromisedPure = yes,
- inlining__can_inline_proc(PredId, ProcId, BuiltinState,
- HighLevelCode, InlinePromisedPure,
- CallingPredMarkers, ModuleInfo),
+ inlining__can_inline_proc_2(PredId, ProcId, BuiltinState,
+ HighLevelCode, InlinePromisedPure, CallingPredMarkers, ModuleInfo),
% OK, we could inline it - but should we? Apply our heuristic.
- (
module_info_pred_info(ModuleInfo, PredId, PredInfo),
- pred_info_requested_inlining(PredInfo)
+ pred_info_get_markers(PredInfo, Markers),
+ ( check_marker(Markers, user_marked_inline) ->
+ UserReq = yes
+ ;
+ ( check_marker(Markers, heuristic_inline)
+ ; set__member(proc(PredId, ProcId), InlinedProcs)
+ )
+ ->
+ UserReq = no
;
- set__member(proc(PredId, ProcId), InlinedProcs)
+ fail
).
inlining__can_inline_proc(PredId, ProcId, BuiltinState, InlinePromisedPure,
CallingPredMarkers, ModuleInfo) :-
module_info_globals(ModuleInfo, Globals),
globals__lookup_bool_option(Globals, highlevel_code, HighLevelCode),
- inlining__can_inline_proc(PredId, ProcId, BuiltinState,
+ inlining__can_inline_proc_2(PredId, ProcId, BuiltinState,
HighLevelCode, InlinePromisedPure,
CallingPredMarkers, ModuleInfo).
-:- pred inlining__can_inline_proc(pred_id::in, proc_id::in, builtin_state::in,
- bool::in, bool::in, pred_markers::in, module_info::in) is semidet.
+:- pred inlining__can_inline_proc_2(pred_id::in, proc_id::in,
+ builtin_state::in, bool::in, bool::in, pred_markers::in, module_info::in)
+ is semidet.
-inlining__can_inline_proc(PredId, ProcId, BuiltinState, HighLevelCode,
+inlining__can_inline_proc_2(PredId, ProcId, BuiltinState, HighLevelCode,
InlinePromisedPure, CallingPredMarkers, ModuleInfo) :-
% Don't inline builtins, the code generator will handle them.
Index: compiler/intermod.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/intermod.m,v
retrieving revision 1.176
diff -u -b -r1.176 intermod.m
--- compiler/intermod.m 12 Sep 2005 05:24:09 -0000 1.176
+++ compiler/intermod.m 12 Sep 2005 07:07:32 -0000
@@ -354,7 +354,7 @@
(
inlining__is_simple_clause_list(Clauses, InlineThreshold + Arity),
pred_info_get_markers(PredInfo, Markers),
- \+ check_marker(Markers, no_inline)
+ \+ check_marker(Markers, user_marked_no_inline)
;
pred_info_requested_inlining(PredInfo)
;
@@ -1784,8 +1784,9 @@
% The warning for calls to local obsolete predicates should appear
% once in the defining module, not in importing modules.
intermod__should_output_marker(obsolete, no).
-intermod__should_output_marker(inline, yes).
-intermod__should_output_marker(no_inline, yes).
+intermod__should_output_marker(user_marked_inline, yes).
+intermod__should_output_marker(user_marked_no_inline, yes).
+intermod__should_output_marker(heuristic_inline, no).
intermod__should_output_marker(dnf, yes).
intermod__should_output_marker(aditi, yes).
intermod__should_output_marker(base_relation, yes).
Index: compiler/options.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.465
diff -u -b -r1.465 options.m
--- compiler/options.m 12 Sep 2005 03:03:00 -0000 1.465
+++ compiler/options.m 12 Sep 2005 03:19:02 -0000
@@ -466,6 +466,7 @@
; inline_simple
; inline_builtins
; inline_single_use
+ ; inline_call_cost
; inline_compound_threshold
; inline_simple_threshold
; inline_vars_threshold
@@ -1164,6 +1165,7 @@
inline_simple - bool(no),
inline_builtins - bool(yes),
inline_single_use - bool(no),
+ inline_call_cost - int(0),
inline_compound_threshold - int(0),
inline_simple_threshold - int(5), % has no effect until
% --inline-simple is enabled
@@ -1825,6 +1827,7 @@
long_option("inline-simple", inline_simple).
long_option("inline-builtins", inline_builtins).
long_option("inline-single-use", inline_single_use).
+long_option("inline-call-cost", inline_call_cost).
long_option("inline-compound-threshold", inline_compound_threshold).
long_option("inline-simple-threshold", inline_simple_threshold).
long_option("intermod-inline-simple-threshold",
@@ -3833,11 +3836,15 @@
"\tbuiltins is not traced.",
"--no-inline-single-use",
"\tDisable the inlining of procedures called only once.",
+ "--inline-call-cost <cost>",
+ "\tAssume that the cost of a call is the given parameter.",
+ "\tUsed only in conjunction with --inline-compound-threshold.",
+ "\tmultiplied by the number of times it is called,",
"--inline-compound-threshold <threshold>",
"\tInline a procedure if its size (measured roughly",
- "\tin terms of the number of connectives in its internal form),",
- "\tmultiplied by the number of times it is called,",
- "\tis below the given threshold.",
+ "\tin terms of the number of connectives in its internal form)",
+ "\tless the assumed call cost, multiplied by the number of times",
+ "\tit is called is below the given threshold.",
"--inline-simple-threshold <threshold>",
"\tInline a procedure if its size is less than the",
"\tgiven threshold.",
Index: compiler/table_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/table_gen.m,v
retrieving revision 1.90
diff -u -b -r1.90 table_gen.m
--- compiler/table_gen.m 12 Sep 2005 05:24:25 -0000 1.90
+++ compiler/table_gen.m 12 Sep 2005 07:07:34 -0000
@@ -1809,8 +1809,9 @@
keep_marker(infer_type) = no.
keep_marker(infer_modes) = no.
keep_marker(obsolete) = no.
-keep_marker(inline) = no.
-keep_marker(no_inline) = no.
+keep_marker(user_marked_inline) = no.
+keep_marker(user_marked_no_inline) = no.
+keep_marker(heuristic_inline) = no.
keep_marker(dnf) = no.
keep_marker(aditi) = no. % consider calling error
keep_marker(base_relation) = no. % consider calling error
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing debian/patches
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/aditi
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/stream
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing mdbcomp
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing slice
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
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