[m-dev.] for review: recognise associativity assertions
Peter Ross
petdr at cs.mu.OZ.AU
Fri Dec 24 14:16:46 AEDT 1999
On 20-Dec-1999, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> On 20-Dec-1999, Peter Ross <petdr at cs.mu.OZ.AU> wrote:
> >
> > Is it alright to check this code in?
>
> I'd like to see a diff for your updated changes first
> (preferably both a relative diff and complete diff).
>
Here is the relative diff of my changes followed by the full diff (the
changes to the test directory are at the end).
--- accumulator.m.old Thu Dec 23 17:24:19 1999
+++ accumulator.m Fri Dec 24 13:15:41 1999
@@ -242,7 +242,7 @@
{ pred_info_context(PredInfo, Context) },
error_util__write_error_pieces(Context, 0,
- [words("In the"), words(PredName)]),
+ [words("The"), words(PredName)]),
{ proc_info_varset(ProcInfo, VarSet) },
accumulator__warnings(Warnings, VarSet, ModuleInfo1),
@@ -254,15 +254,50 @@
words("do not introduce"),
words("performance problems."),
words("These warnings can"),
- words("be supressed by"),
- words("--inhibit-accumulator-warnings.")
+ words("be suppressed by"),
+ words("`--inhibit-accumulator-warnings'.")
]),
+ globals__io_lookup_bool_option(verbose_errors,
+ VerboseErrors),
+ (
+ { VerboseErrors = yes }
+ ->
+ error_util__write_error_pieces(Context, 2,
+ [
+ words("If a predicate has been"),
+ words("declared associative via"),
+ words("a promise declaration,"),
+ words("the compiler will"),
+ words("rearrange the order"),
+ words("of the arguments"),
+ words("in calls to that"),
+ words("predicate, if by so doing"),
+ words("it makes the containing"),
+ words("predicate tail recursive."),
+ words("In such situations, the"),
+ words("compiler will issue"),
+ words("this warning."),
+ words("If this reordering changes the"),
+ words("performance characteristics"),
+ words("of the call to the"),
+ words("predicate, use"),
+ words("`--no-accumulator-introduction'"),
+ words("to turn the optimization"),
+ words("off, or"),
+ words("`--inhibit-accumulator-warnings'"),
+ words("to turn off the warnings.")
+ ])
+ ;
+ []
+ ),
+
globals__io_lookup_bool_option(halt_at_warn,
HaltAtWarn),
(
{ HaltAtWarn = yes }
->
+ io__set_exit_status(1),
{ module_info_incr_errors(ModuleInfo1,
ModuleInfo) }
;
@@ -327,7 +362,7 @@
error_util__describe_one_pred_name(ModuleInfo, PredId, PredStr),
varset__lookup_name(VarSet, VarA, VarAStr),
varset__lookup_name(VarSet, VarB, VarBStr),
- Formats = [words("warning: The"), words(PredStr),
+ Formats = [words("warning: the call to"), words(PredStr),
words("has had the location of the variables"),
words(VarAStr), words("and"), words(VarBStr),
words("swapped to allow accumulator introduction.")
--- assertion.m.old Thu Dec 23 17:24:19 1999
+++ assertion.m Thu Dec 23 17:20:15 1999
@@ -189,7 +189,9 @@
% If you read the predicate documentation, you will note
% that for each pair of variables on the left hand side
% their is an equivalent pair of variables on the right
- % hand side.
+ % hand side. As the pairs of variables are not
+ % symmetric, the call to list__perm will only succeed
+ % once, if at all.
assoc_list__from_corresponding_lists(PairsL, PairsR, Pairs),
list__perm(Pairs, [(A - AB) - (B - A), (B - C) - (C - BC),
(AB - ABC) - (BC - ABC)]),
===================================================================
Estimated hours taken: 35
Recognise associativity assertions, and use them to introduce
accumulators.
mercury/compiler/assertion.m:
Add assertion__is_associativity_assertion, which for an assert_id
determines whether the assertion is associative.
mercury/compiler/accumulator.m:
Call assertion__is_associativity_assertion to determine whether a
call is associative.
Rather than failing if a call is associative and nothing is known
about the effect of rearranging the argument order, report a
suppressible warning.
Fix a bug where the mode of the introduced pred wasn't correct.
mercury/compiler/mercury_compile.m:
Move accumulator introduction before inlining and unused_args, as
inlining can inline an associative call making it unrecognisable and
unused_args eliminates arguments which make it difficult to relate
the assertion with the actual call.
mercury/compiler/notes/compiler_design.html:
Document the constraints on when the module accumulator.m can be
called for it to be effective.
mercury/compiler/options.m:
Add the new option "--inhibit-accumulator-warnings".
mercury/doc/user_guide.texi:
Document "--inhibit-accumulator-warnings".
mercury/library/list.m:
Declare list__append to be associative.
tests/general/accumulator/runtests:
Turn the tests back on, they *should* work under different
optimization levels now.
tests/warnings/Mmakefile:
tests/warnings/arg_order_rearrangment.exp:
tests/warnings/arg_order_rearrangment.m:
Test that a warning is output when accumulator introduction reorders
the arguments to a call without knowing the performance
implications.
Index: promise/compiler/accumulator.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/accumulator.m,v
retrieving revision 1.7
diff -u -r1.7 accumulator.m
--- promise/compiler/accumulator.m 1999/09/12 04:26:36 1.7
+++ promise/compiler/accumulator.m 1999/12/24 02:15:41
@@ -95,8 +95,8 @@
:- implementation.
-:- import_module (assertion), goal_util, globals.
-:- import_module hlds_data, hlds_goal, hlds_out.
+:- import_module (assertion), error_util, goal_util, globals.
+:- import_module hlds_data, hlds_goal, hlds_out, (inst).
:- import_module inst_match, instmap, mode_util, options, prog_data, prog_util.
:- import_module assoc_list, bool, list, map, multi_map.
@@ -163,9 +163,17 @@
orig_dynvar_map,
subst, % Y0s -> As
subst, % Hs -> As
- set(prog_var) % Ys
+ set(prog_var), % Ys
+ warnings
).
+:- type warning
+ % warn that two prog_vars in call to pred_id
+ % at prog_context were swapped.
+ ---> w(prog_context, pred_id, prog_var, prog_var).
+
+:- type warnings == list(warning).
+
% is the pred commutative?
:- type commutative == bool.
@@ -209,7 +217,7 @@
{ module_info_pred_info(ModuleInfo0, PredId, PredInfo) },
{ accumulator__attempt_transform(ProcId, ProcInfo0, PredId,
PredInfo, DoLCO, FullyStrict, ModuleInfo0,
- ProcInfo1, ModuleInfo1) }
+ Warnings, ProcInfo1, ModuleInfo1) }
->
globals__io_lookup_bool_option(very_verbose, VeryVerbose),
(
@@ -222,8 +230,81 @@
[]
),
- { ProcInfo = ProcInfo1 },
- { ModuleInfo = ModuleInfo1 }
+ globals__io_lookup_bool_option(inhibit_accumulator_warnings,
+ InhibitWarnings),
+ (
+ ( { Warnings = [] } ; { InhibitWarnings = yes } )
+ ->
+ { ModuleInfo = ModuleInfo1 }
+ ;
+ { error_util__describe_one_pred_name(ModuleInfo1,
+ PredId, PredName) },
+ { pred_info_context(PredInfo, Context) },
+
+ error_util__write_error_pieces(Context, 0,
+ [words("The"), words(PredName)]),
+
+ { proc_info_varset(ProcInfo, VarSet) },
+ accumulator__warnings(Warnings, VarSet, ModuleInfo1),
+
+ error_util__write_error_pieces(Context, 2,
+ [
+ words("Please ensure that these"),
+ words("argument rearrangements"),
+ words("do not introduce"),
+ words("performance problems."),
+ words("These warnings can"),
+ words("be suppressed by"),
+ words("`--inhibit-accumulator-warnings'.")
+ ]),
+
+ globals__io_lookup_bool_option(verbose_errors,
+ VerboseErrors),
+ (
+ { VerboseErrors = yes }
+ ->
+ error_util__write_error_pieces(Context, 2,
+ [
+ words("If a predicate has been"),
+ words("declared associative via"),
+ words("a promise declaration,"),
+ words("the compiler will"),
+ words("rearrange the order"),
+ words("of the arguments"),
+ words("in calls to that"),
+ words("predicate, if by so doing"),
+ words("it makes the containing"),
+ words("predicate tail recursive."),
+ words("In such situations, the"),
+ words("compiler will issue"),
+ words("this warning."),
+ words("If this reordering changes the"),
+ words("performance characteristics"),
+ words("of the call to the"),
+ words("predicate, use"),
+ words("`--no-accumulator-introduction'"),
+ words("to turn the optimization"),
+ words("off, or"),
+ words("`--inhibit-accumulator-warnings'"),
+ words("to turn off the warnings.")
+ ])
+ ;
+ []
+ ),
+
+ globals__io_lookup_bool_option(halt_at_warn,
+ HaltAtWarn),
+ (
+ { HaltAtWarn = yes }
+ ->
+ io__set_exit_status(1),
+ { module_info_incr_errors(ModuleInfo1,
+ ModuleInfo) }
+ ;
+ { ModuleInfo = ModuleInfo1 }
+ )
+ ),
+ { ProcInfo = ProcInfo1 }
;
{ ProcInfo = ProcInfo0 },
{ ModuleInfo = ModuleInfo0 }
@@ -236,10 +317,10 @@
%
:- pred accumulator__attempt_transform(proc_id::in, proc_info::in,
pred_id::in, pred_info::in, bool::in, bool::in, module_info::in,
- proc_info::out, module_info::out) is semidet.
+ warnings::out, proc_info::out, module_info::out) is semidet.
accumulator__attempt_transform(ProcId, ProcInfo0, PredId, PredInfo0, DoLCO,
- FullyStrict, ModuleInfo0, ProcInfo, ModuleInfo) :-
+ FullyStrict, ModuleInfo0, Warnings, ProcInfo, ModuleInfo) :-
proc_info_goal(ProcInfo0, Goal0),
proc_info_headvars(ProcInfo0, HeadVars),
proc_info_get_initial_instmap(ProcInfo0, ModuleInfo0, InitialInstMap),
@@ -254,7 +335,7 @@
accumulator__transform(GoalType, Base, Rec, Goal, DoLCO, FullyStrict,
ModuleInfo1, HeadVars, HstoAs_Subst, NewPredId,
- NewProcId, NewPredName, OrigGoal, AccGoal),
+ NewProcId, NewPredName, OrigGoal, Warnings, AccGoal),
accumulator__update_accumulator_pred(NewPredId, NewProcId, AccGoal,
ModuleInfo1, ModuleInfo),
@@ -264,6 +345,33 @@
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
+:- pred accumulator__warnings(list(warning)::in, prog_varset::in,
+ module_info::in, io__state::di, io__state::uo) is det.
+
+accumulator__warnings([], _, _) --> [].
+accumulator__warnings([W | Ws], VarSet, ModuleInfo) -->
+ { accumulator__warning(W, VarSet, ModuleInfo, Context, Format) },
+ error_util__write_error_pieces(Context, 2, Format),
+ accumulator__warnings(Ws, VarSet, ModuleInfo).
+
+:- pred accumulator__warning(warning::in, prog_varset::in, module_info::in,
+ prog_context::out, list(format_component)::out) is det.
+
+accumulator__warning(w(Context, PredId, VarA, VarB), VarSet, ModuleInfo,
+ Context, Formats) :-
+ error_util__describe_one_pred_name(ModuleInfo, PredId, PredStr),
+ varset__lookup_name(VarSet, VarA, VarAStr),
+ varset__lookup_name(VarSet, VarB, VarBStr),
+ Formats = [words("warning: the call to"), words(PredStr),
+ words("has had the location of the variables"),
+ words(VarAStr), words("and"), words(VarBStr),
+ words("swapped to allow accumulator introduction.")
+ ].
+
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
%
% accumulator__simplify
%
@@ -549,7 +657,13 @@
map__lookup(VarTypes0, Var, Type),
map__det_insert(VarTypes1, NewVar, Type, VarTypes),
- instmap__lookup_var(InstMap, Var, Inst),
+ % XXX we don't want to use the inst of the var as it can
+ % be more specific than it should be. ie int_const(1)
+ % when it should be any integer.
+ % However this will no longer handle partially
+ % instantiated data structures.
+ % instmap__lookup_var(InstMap, Var, Inst),
+ Inst = ground(shared, no),
inst_lists_to_mode_list([Inst], [Inst], Mode),
list__append(Mode, Modes0, Modes).
@@ -605,11 +719,12 @@
hlds_goal::in, bool::in, bool::in, module_info::in,
prog_vars::in, subst::in, pred_id::in,
proc_id::in, sym_name::in,
- hlds_goal::out, hlds_goal::out) is semidet.
+ hlds_goal::out, warnings::out, hlds_goal::out) is semidet.
accumulator__transform(TopLevel, base(BaseGoalList), recursive(PreDP, DP, R, C),
- Goal, DoLCO, FullyStrict, ModuleInfo, HeadVars, HstoAs_Subst,
- NewPredId, NewProcId, NewPredName, OrigGoal, NewGoal) :-
+ Goal, DoLCO, FullyStrict, ModuleInfo, HeadVars,
+ HstoAs_Subst, NewPredId, NewProcId, NewPredName,
+ OrigGoal, Warnings, NewGoal) :-
accumulator__Ys_descended_from_Y0s(HeadVars, DP, ModuleInfo),
@@ -623,8 +738,8 @@
Y0stoYs_Subst, HstoAs_Subst, NewBaseGoal),
accumulator__new_recursive_case(DP, C, R, DoLCO, FullyStrict,
ModuleInfo, NewPredId, NewProcId, NewPredName,
- Vars, HeadVars,
- Y0stoYs_Subst, HstoAs_Subst, NewRecGoal),
+ Vars, HeadVars, Y0stoYs_Subst, HstoAs_Subst,
+ Warnings, NewRecGoal),
accumulator__top_level(TopLevel, Goal, OrigBaseGoal, OrigRecGoal,
NewBaseGoal, NewRecGoal, OrigGoal, NewGoal).
@@ -1073,11 +1188,11 @@
a_goal::in, bool::in, bool::in,
module_info::in, pred_id::in, proc_id::in,
sym_name::in, prog_vars::in, prog_vars::in, subst::in,
- subst::in, hlds_goal::out) is semidet.
+ subst::in, warnings::out, hlds_goal::out) is semidet.
accumulator__new_recursive_case(DP, C, R0, DoLCO, FullyStrict,
ModuleInfo, PredId, ProcId, Name, Hs, HeadVars,
- Y0stoYs_Subst, HstoAs_Subst, Goal) :-
+ Y0stoYs_Subst, HstoAs_Subst, Warnings, Goal) :-
DP = goal(DecomposeProcess, _InstMapBeforeDecomposeProcess),
C = goal(Compose, InstMapBeforeCompose),
R0 = goal(Recursive0, _InstMapBeforeRecursive0),
@@ -1107,6 +1222,7 @@
),
assoc_info_Y0stoAs(Y0stoAs_Subst, AssocInfo, _),
+ assoc_info_warnings(Warnings, AssocInfo, _),
accumulator__rename_prerec_goals(PreRecGoal0, Y0stoAs_Subst,
Y0stoYs_Subst, LCO_Subst, HstoAs_Subst, PreRecGoal),
@@ -1347,21 +1463,10 @@
assoc_info_module_info(ModuleInfo),
accumulator__call_dynamic_var(Arg0s, DynamicCallVar),
- { accumulator__is_associative(PredId, ProcId, ModuleInfo, Arg0s, Args,
- PossibleStaticVars, Commutative) },
+ { goal_info_get_context(GoalInfo, ProgContext) },
+ accumulator__is_associative(PredId, ProcId, ProgContext, ModuleInfo,
+ Arg0s, Args, PossibleStaticVars, Commutative),
- (
- % Make sure that after rearrangement of the
- % arguments the new proc will be at least as
- % efficient as the old pred.
- { Commutative = no },
- assoc_info_static_set(StaticSet),
- { accumulator__obey_heuristic(PredId, ModuleInfo,
- Args, StaticSet) }
- ;
- { Commutative = yes }
- ),
-
accumulator__check_previous_calls(DynamicCallVar,
PredId, ProcId, Commutative),
accumulator__new_dynamic_var(Arg0s, DynamicCallVar, NewDynamicVar),
@@ -1630,12 +1735,14 @@
% and an indicator of whether or not the predicate is
% commutative.
%
-:- pred accumulator__is_associative(pred_id::in, proc_id::in, module_info::in,
- prog_vars::in, prog_vars::out, set(prog_var)::out,
- commutative::out) is semidet.
+:- pred accumulator__is_associative(pred_id::in, proc_id::in, prog_context::in,
+ module_info::in, prog_vars::in, prog_vars::out,
+ set(prog_var)::out, commutative::out,
+ assoc_info::in, assoc_info::out) is semidet.
-accumulator__is_associative(PredId, ProcId, ModuleInfo,
- Args0, Args, PossibleStaticVars, Commutative):-
+accumulator__is_associative(PredId, ProcId, Context, ModuleInfo,
+ Args0, Args, PossibleStaticVars, Commutative,
+ AssocInfo0, AssocInfo):-
module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
PredInfo, ProcInfo),
@@ -1649,19 +1756,85 @@
check_modes(Args0, PossibleStaticVars0, Modes, ModuleInfo),
Args = Args0,
PossibleStaticVars = PossibleStaticVars0,
+ AssocInfo = AssocInfo0,
Commutative = yes
;
+ associativity_assertion(set__to_sorted_list(Assertions),
+ ModuleInfo, Args0, VarA - VarB),
+
+ PossibleStaticVars = set__list_to_set([VarA, VarB]),
+
+ % Swap the order of the arguments
+ list__map((pred(V0::in, V::out) is det :-
+ (
+ V0 = VarA
+ ->
+ V = VarB
+ ;
+ V0 = VarB
+ ->
+ V = VarA
+ ;
+ V = V0
+ )
+ ), Args0, Args),
- % Check if it is associative
+ check_modes(Args, PossibleStaticVars, Modes, ModuleInfo),
+
+ % Determine what variables can be static
pred_info_module(PredInfo, ModuleName),
pred_info_name(PredInfo, PredName),
pred_info_arity(PredInfo, Arity),
-
- assoc_fact(ModuleName, PredName, Arity, Modes,
- ModuleInfo, Args0, Args, PossibleStaticVars),
+ (
+ has_heuristic(ModuleName, PredName, Arity)
+ ->
+ % If there is a heuristic for that call
+ % then ensure that the call obeys
+ % the heuristic that the static
+ % variables are in certain positions.
+ %
+ % For example, a call to append in the
+ % forward mode will have the following
+ % types of variables: (static, dynamic,
+ % dynamic). After rearrangment that
+ % order will be (dynamic, static,
+ % dynamic). Having a dynamic variable
+ % in the first position will probably
+ % take O(N) time to process while having
+ % a static variable will probably take
+ % O(1) time. Therefore the complexity
+ % of the predicate as a whole will
+ % change, we must ensure that it changes
+ % for the better.
+ %
+ heuristic(ModuleName, PredName, Arity, Args,
+ MustBeStaticVars),
+ assoc_info_static_set(StaticSet, AssocInfo0,
+ AssocInfo),
+ (StaticSet `intersect` MustBeStaticVars) `equal`
+ MustBeStaticVars
+ ;
+ % If no heuristic is known, then record
+ % which variables were swapped and warn
+ % the user.
+ assoc_info_add_warning(w(Context, PredId, VarA, VarB),
+ AssocInfo0, AssocInfo)
+ ),
Commutative = no
).
+
+:- pred has_heuristic(module_name::in, string::in, arity::in) is semidet.
+
+has_heuristic(unqualified("list"), "append", 3).
+
+:- pred heuristic(module_name::in, string::in, arity::in, prog_vars::in,
+ set(prog_var)::out) is semidet.
+
+heuristic(unqualified("list"), "append", 3, [_Typeinfo, A, _B, _C], Set) :-
+ set__list_to_set([A], Set).
+
+
%
% commutativity_assertion
%
@@ -1690,6 +1863,31 @@
%
+ % associativity_assertion
+ %
+ % Does there exist one (and only one) associativity assertion for the
+ % current predicate.
+ % The 'and only one condition' is required because we currently
+ % don't handle the case of predicates which have individual
+ % parts which are associative, because then we don't know which
+ % variable is descended from which.
+ %
+:- pred associativity_assertion(list(assert_id)::in, module_info::in,
+ prog_vars::in, pair(prog_var)::out) is semidet.
+
+associativity_assertion([AssertId | AssertIds], ModuleInfo, Args0, VarAB) :-
+ (
+ assertion__is_associativity_assertion(AssertId, ModuleInfo,
+ Args0, VarAB0)
+ ->
+ \+ associativity_assertion(AssertIds, ModuleInfo, Args0, _),
+ VarAB = VarAB0
+ ;
+ associativity_assertion(AssertIds, ModuleInfo, Args0, VarAB)
+ ).
+
+
+ %
% check_modes(Vs, CVs, Ms, MI)
%
% Given a list of variables, Vs, and associated modes, Ms, make
@@ -1713,106 +1911,9 @@
check_modes(Vs, PossibleStaticVars, Ms, ModuleInfo).
- %
- % XXX this fact table is only a temporary solution to whether or
- % not a particular procedure is associative. In the long term
- % the user should be able to annotate their code to indicate
- % which predicates are associative.
- %
- % The set is simply the set of vars that must be static. It is
- % a simple heuristic to ensure that the O() behaviour only
- % improves. ie for append after swapping the arguments the
- % static variable must be in the first location.
- %
-:- pred assoc_fact(module_name::in, string::in, arity::in,
- list(mode)::in, module_info::in, prog_vars::in,
- prog_vars::out, set(prog_var)::out) is semidet.
-
-assoc_fact(unqualified("list"), "append", 3, [TypeInfoIn, In, In, Out],
- ModuleInfo, [TypeInfo, A, B, C],
- [TypeInfo, B, A, C], PossibleStaticVars) :-
- set__list_to_set([A, B], PossibleStaticVars),
- mode_is_input(ModuleInfo, TypeInfoIn),
- mode_is_input(ModuleInfo, In),
- mode_is_output(ModuleInfo, Out).
-
-
-
-/* XXX introducing accumulators for floating point numbers can be bad.
-assoc_fact(unqualified("float"), "+", 3, [In, In, Out], ModuleInfo,
- [A, B, C], [A, B, C], PossibleStaticVars, no) :-
- set__list_to_set([A, B], PossibleStaticVars),
- mode_is_input(ModuleInfo, In),
- mode_is_output(ModuleInfo, Out).
-
-assoc_fact(unqualified("float"), "*", 3, [In, In, Out], ModuleInfo,
- [A, B, C], [A, B, C], PossibleStaticVars, no) :-
- set__list_to_set([A, B], PossibleStaticVars),
- mode_is_input(ModuleInfo, In),
- mode_is_output(ModuleInfo, Out).
-*/
-/*
- XXX this no longer works, because set__insert isn't associative.
-
- However set__insert obeys the following axiom, providing that you
- use user-defined equality (set__equals), not structural equality
- for S.
-
- some [SA] (p(A, S0, SA), p(B, SA, S)) <=>
- some [SB] (p(B, S0, SB), p(A, SB, S))
-
- My previous attempt at this transformation handled this case
- and I thought the current one did as well. I was wrong. I need
- to reintegrate my old code.
-
-assoc_fact(unqualified("set"), "insert", 3, [TypeInfoIn, In, In, Out],
- Moduleinfo, [TypeInfo, A, B, C],
- [TypeInfo, A, B, C], PossibleStaticVars, no) :-
- set__list_to_set([A, B], PossibleStaticVars),
- mode_is_input(Moduleinfo, TypeInfoIn),
- mode_is_input(Moduleinfo, In),
- mode_is_output(Moduleinfo, Out).
-*/
-
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
- %
- % accumulator__obey_heuristic
- %
- % for calls which rearrange the order of variables ensure that
- % the call obeys the heuristic that the static variables are in
- % certain positions.
- %
- % For example, a call to append in the forward mode will have
- % the following types of variables: (static, dynamic, dynamic).
- % After rearrangment that order will be (dynamic, static, dynamic).
- % Having a dynamic variable in the first position will probably
- % take O(N) time to process while having a static variable will
- % probably take O(1) time. Therefore the complexity of the
- % predicate as a whole will change, we must ensure that it
- % changes for the better.
- %
-:- pred accumulator__obey_heuristic(pred_id::in, module_info::in,
- prog_vars::in, set(prog_var)::in) is semidet.
-
-accumulator__obey_heuristic(Predid, ModuleInfo, Args, StaticSet) :-
- module_info_pred_info(ModuleInfo, Predid, PredInfo),
- pred_info_module(PredInfo, ModuleName),
- pred_info_name(PredInfo, PredName),
- pred_info_arity(PredInfo, Arity),
- heuristic(ModuleName, PredName, Arity, Args, MustBeStaticVars),
- set__intersect(StaticSet, MustBeStaticVars, Intersection),
- set__equal(MustBeStaticVars, Intersection).
-
-:- pred heuristic(module_name::in, string::in, arity::in, prog_vars::in,
- set(prog_var)::out) is semidet.
-
-heuristic(unqualified("list"), "append", 3, [_Typeinfo, A, _B, _C], Set) :-
- set__list_to_set([A], Set).
-
-%-----------------------------------------------------------------------------%
-
:- pred assoc_info_init(module_info::in, prog_vars::in, a_goals::in,
a_goals::in, a_goal::in,
subst::in, subst::in, assoc_info::out) is det.
@@ -1864,76 +1965,91 @@
%
set__list_to_set(Ys, YsSet),
+ ErrorMessages = [],
+
AssocInfo = assoc_info(StaticSet, DynamicSet,
ModuleInfo, PrevCallMap, OrigDynVarMap,
- Y0stoAs_Subst, HstoAs_Subst, YsSet).
+ Y0stoAs_Subst, HstoAs_Subst, YsSet,
+ ErrorMessages).
:- pred assoc_info_static_set(set(prog_var)::out,
assoc_info::in, assoc_info::out) is det.
assoc_info_static_set(StaticSet, AssocInfo, AssocInfo) :-
- AssocInfo = assoc_info(StaticSet, _, _, _, _, _, _, _).
+ AssocInfo = assoc_info(StaticSet, _, _, _, _, _, _, _, _).
:- pred assoc_info_dynamic_set(set(prog_var)::out,
assoc_info::in, assoc_info::out) is det.
assoc_info_dynamic_set(DynamicSet, AssocInfo, AssocInfo) :-
- AssocInfo = assoc_info(_, DynamicSet, _, _, _, _, _, _).
+ AssocInfo = assoc_info(_, DynamicSet, _, _, _, _, _, _, _).
:- pred assoc_info_module_info(module_info::out,
assoc_info::in, assoc_info::out) is det.
assoc_info_module_info(ModuleInfo, AssocInfo, AssocInfo) :-
- AssocInfo = assoc_info(_, _, ModuleInfo, _, _, _, _, _).
+ AssocInfo = assoc_info(_, _, ModuleInfo, _, _, _, _, _, _).
:- pred assoc_info_prev_call_map(prev_call_map::out,
assoc_info::in, assoc_info::out) is det.
assoc_info_prev_call_map(PrevCallMap, AssocInfo, AssocInfo) :-
- AssocInfo = assoc_info(_, _, _, PrevCallMap, _, _, _, _).
+ AssocInfo = assoc_info(_, _, _, PrevCallMap, _, _, _, _, _).
:- pred assoc_info_orig_dynvar_map(orig_dynvar_map::out,
assoc_info::in, assoc_info::out) is det.
assoc_info_orig_dynvar_map(OrigDynVarMap, AssocInfo, AssocInfo) :-
- AssocInfo = assoc_info(_, _, _, _, OrigDynVarMap, _, _, _).
+ AssocInfo = assoc_info(_, _, _, _, OrigDynVarMap, _, _, _, _).
:- pred assoc_info_Y0stoAs(subst::out,
assoc_info::in, assoc_info::out) is det.
assoc_info_Y0stoAs(Y0stoAs_Subst, AssocInfo, AssocInfo) :-
- AssocInfo = assoc_info(_, _, _, _, _, Y0stoAs_Subst, _, _).
+ AssocInfo = assoc_info(_, _, _, _, _, Y0stoAs_Subst, _, _, _).
:- pred assoc_info_HstoAs(subst::out,
assoc_info::in, assoc_info::out) is det.
assoc_info_HstoAs(HstoAs_Subst, AssocInfo, AssocInfo) :-
- AssocInfo = assoc_info(_, _, _, _, _, _, HstoAs_Subst, _).
+ AssocInfo = assoc_info(_, _, _, _, _, _, HstoAs_Subst, _, _).
:- pred assoc_info_Ys(set(prog_var)::out,
assoc_info::in, assoc_info::out) is det.
assoc_info_Ys(Ys, AssocInfo, AssocInfo) :-
- AssocInfo = assoc_info(_, _, _, _, _, _, _, Ys).
+ AssocInfo = assoc_info(_, _, _, _, _, _, _, Ys, _).
+:- pred assoc_info_warnings(warnings::out,
+ assoc_info::in, assoc_info::out) is det.
+assoc_info_warnings(Warnings, AssocInfo, AssocInfo) :-
+ AssocInfo = assoc_info(_, _, _, _, _, _, _, _, Warnings).
+
/*
:- pred assoc_info_set_static_set(set(prog_var)::in, assoc_info::in,
assoc_info::out) is det.
-assoc_info_set_static_set(StaticSet, assoc_info(_, B, C, D, E, F, G, H),
- assoc_info(StaticSet, B, C, D, E, F, G, H)).
+assoc_info_set_static_set(StaticSet, assoc_info(_, B, C, D, E, F, G, H, I),
+ assoc_info(StaticSet, B, C, D, E, F, G, H, I)).
*/
:- pred assoc_info_set_dynamic_set(set(prog_var)::in, assoc_info::in,
assoc_info::out) is det.
-assoc_info_set_dynamic_set(DynamicSet, assoc_info(A, _, C, D, E, F, G, H),
- assoc_info(A, DynamicSet, C, D, E, F, G, H)).
+assoc_info_set_dynamic_set(DynamicSet, assoc_info(A, _, C, D, E, F, G, H, I),
+ assoc_info(A, DynamicSet, C, D, E, F, G, H, I)).
:- pred assoc_info_set_prev_call_map(prev_call_map::in, assoc_info::in,
assoc_info::out) is det.
-assoc_info_set_prev_call_map(PrevCallMap, assoc_info(A, B, C, _, E, F, G, H),
- assoc_info(A, B, C, PrevCallMap, E, F, G, H)).
+assoc_info_set_prev_call_map(PrevCallMap, assoc_info(A, B, C, _, E, F, G, H, I),
+ assoc_info(A, B, C, PrevCallMap, E, F, G, H, I)).
:- pred assoc_info_set_orig_dynvar_map(orig_dynvar_map::in, assoc_info::in,
assoc_info::out) is det.
-assoc_info_set_orig_dynvar_map(OrigDynMap, assoc_info(A, B, C, D, _, F, G, H),
- assoc_info(A, B, C, D, OrigDynMap, F, G, H)).
+assoc_info_set_orig_dynvar_map(OrigDynMap,
+ assoc_info(A, B, C, D, _, F, G, H, I),
+ assoc_info(A, B, C, D, OrigDynMap, F, G, H, I)).
:- pred assoc_info_set_Y0stoAs(subst::in, assoc_info::in,
+ assoc_info::out) is det.
+assoc_info_set_Y0stoAs(Y0stoAs_Subst, assoc_info(A, B, C, D, E, _, G, H, I),
+ assoc_info(A, B, C, D, E, Y0stoAs_Subst, G, H, I)).
+
+:- pred assoc_info_add_warning(warning::in, assoc_info::in,
assoc_info::out) is det.
-assoc_info_set_Y0stoAs(Y0stoAs_Subst, assoc_info(A, B, C, D, E, _, G, H),
- assoc_info(A, B, C, D, E, Y0stoAs_Subst, G, H)).
+assoc_info_add_warning(Warning,
+ assoc_info(A, B, C, D, E, F, G, H, Warnings),
+ assoc_info(A, B, C, D, E, F, G, H, [Warning | Warnings])).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: promise/compiler/assertion.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/assertion.m,v
retrieving revision 1.5
diff -u -r1.5 assertion.m
--- promise/compiler/assertion.m 1999/11/12 09:08:12 1.5
+++ promise/compiler/assertion.m 1999/12/23 06:20:15
@@ -58,6 +58,31 @@
prog_vars::in, pair(prog_var)::out) is semidet.
%
+ % assertion__is_associativity_assertion(Id, MI, Vs, CVs)
+ %
+ % Does the assertion represented by the assertion id, Id,
+ % state the associativity of a pred/func?
+ % We extend the usual definition of associativity to apply to
+ % predicates or functions with more than two arguments as
+ % follows by allowing extra arguments which must be invariant.
+ % If so, this predicate returns (in CVs) the two variables which
+ % can be swapped in order if it was a call to Vs.
+ %
+ % The assertion must be in a form similar to this
+ % all [Is,A,B,C,ABC]
+ % (
+ % some [AB] p(Is,A,B,AB), p(Is,AB,C,ABC)
+ % <=>
+ % some [BC] p(Is,B,C,BC), p(Is,A,BC,ABC)
+ % )
+ % for the predicate to return true (note that the invariant
+ % arguments, Is, can be any where providing they are in
+ % identical locations on both sides of the equivalence).
+ %
+:- pred assertion__is_associativity_assertion(assert_id::in, module_info::in,
+ prog_vars::in, pair(prog_var)::out) is semidet.
+
+ %
% assertion__in_interface_check
%
% Ensure that an assertion which is defined in an interface
@@ -73,7 +98,7 @@
:- implementation.
:- import_module globals, goal_util, hlds_out, options, prog_out, type_util.
-:- import_module bool, list, map, require, set, std_util.
+:- import_module assoc_list, bool, list, map, require, set, std_util.
:- type subst == map(prog_var, prog_var).
@@ -124,6 +149,107 @@
Q = VarP,
Ps = Qs
).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+assertion__is_associativity_assertion(AssertId, Module, CallVars,
+ AssociativeVars) :-
+ assertion__goal(AssertId, Module, Goal - GoalInfo),
+ equivalent(Goal - GoalInfo, P, Q),
+
+ goal_info_get_nonlocals(GoalInfo, UniversiallyQuantifiedVars),
+
+ P = some(_, _, conj(PCalls) - _) - _PGoalInfo,
+ Q = some(_, _, conj(QCalls) - _) - _QGoalInfo,
+
+ AssociativeVars = promise_only_solution(associative(PCalls, QCalls,
+ UniversiallyQuantifiedVars, CallVars)).
+
+
+ % associative(Ps, Qs, Us, R)
+ %
+ % If the assertion was in the form
+ % all [Us] (some [] (Ps)) <=> (some [] (Qs))
+ % try and rearrange the order of Ps and Qs so that the assertion
+ % is in the standard from
+ %
+ % compose( A, B, AB), compose(B, C, BC),
+ % compose(AB, C, ABC) <=> compose(A, BC, ABC)
+
+:- pred associative(hlds_goals::in, hlds_goals::in, set(prog_var)::in,
+ prog_vars::in, pair(prog_var)::out) is cc_nondet.
+
+associative(PCalls, QCalls, UniversiallyQuantifiedVars, CallVars,
+ CallVarA - CallVarB) :-
+ reorder(PCalls, QCalls, LHSCalls, RHSCalls),
+ process_one_side(LHSCalls, UniversiallyQuantifiedVars, AB, PairsL, Vs),
+ process_one_side(RHSCalls, UniversiallyQuantifiedVars, BC, PairsR, _),
+
+ % If you read the predicate documentation, you will note
+ % that for each pair of variables on the left hand side
+ % their is an equivalent pair of variables on the right
+ % hand side. As the pairs of variables are not
+ % symmetric, the call to list__perm will only succeed
+ % once, if at all.
+ assoc_list__from_corresponding_lists(PairsL, PairsR, Pairs),
+ list__perm(Pairs, [(A - AB) - (B - A), (B - C) - (C - BC),
+ (AB - ABC) - (BC - ABC)]),
+
+ assoc_list__from_corresponding_lists(Vs, CallVars, AssocList),
+ list__filter((pred(X-_Y::in) is semidet :- X = A),
+ AssocList, [_A - CallVarA]),
+ list__filter((pred(X-_Y::in) is semidet :- X = B),
+ AssocList, [_B - CallVarB]).
+
+ % reorder(Ps, Qs, Ls, Rs)
+ %
+ % Given both sides of the equivalence return another possible
+ % ordering.
+
+:- pred reorder(hlds_goals::in, hlds_goals::in,
+ hlds_goals::out, hlds_goals::out) is nondet.
+
+reorder(PCalls, QCalls, LHSCalls, RHSCalls) :-
+ list__perm(PCalls, LHSCalls),
+ list__perm(QCalls, RHSCalls).
+reorder(PCalls, QCalls, LHSCalls, RHSCalls) :-
+ list__perm(PCalls, RHSCalls),
+ list__perm(QCalls, LHSCalls).
+
+ % process_one_side(Gs, Us, L, Ps)
+ %
+ % Given the list of goals, Gs, which are one side of a possible
+ % associative equivalence, and the universally quantified
+ % variables, Us, of the goals return L the existentially
+ % quantified variable that links the two calls and Ps the list
+ % of variables which are not invariants.
+ %
+ % ie for app(TypeInfo, X, Y, XY), app(TypeInfo, XY, Z, XYZ)
+ % L <= XY and Ps <= [X - XY, Y - Z, XY - XYZ]
+
+:- pred process_one_side(hlds_goals::in, set(prog_var)::in, prog_var::out,
+ assoc_list(prog_var)::out, prog_vars::out) is semidet.
+
+process_one_side(Goals, UniversiallyQuantifiedVars, LinkingVar, Vars, VarsA) :-
+ Goals = [call(PredId, _, VarsA, _, _, _) - _,
+ call(PredId, _, VarsB, _, _, _) - _],
+
+ % Determine the linking variable, L.
+ % By definition it must be existentially quantified and
+ % a member of both variable lists.
+ CommonVars = list_to_set(VarsA) `intersect` list_to_set(VarsB),
+ set__singleton_set(CommonVars `difference` UniversiallyQuantifiedVars,
+ LinkingVar),
+
+ % Filter out all the invariant arguments, and then make
+ % sure that their is only 3 arguments left.
+ assoc_list__from_corresponding_lists(VarsA, VarsB, Vars0),
+ list__filter((pred(X-Y::in) is semidet :- not X = Y), Vars0, Vars),
+ list__length(Vars, number_of_associative_vars).
+
+:- func number_of_associative_vars = int.
+number_of_associative_vars = 3.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: promise/compiler/mercury_compile.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/mercury_compile.m,v
retrieving revision 1.145
diff -u -r1.145 mercury_compile.m
--- promise/compiler/mercury_compile.m 1999/12/21 09:56:36 1.145
+++ promise/compiler/mercury_compile.m 1999/12/23 06:41:55
@@ -36,9 +36,9 @@
:- import_module stratify, check_typeclass, simplify, intermod, trans_opt.
:- import_module table_gen.
:- import_module bytecode_gen, bytecode.
-:- import_module (lambda), termination, higher_order, inlining.
-:- import_module deforest, dnf, unused_args, magic, dead_proc_elim.
-:- import_module accumulator, lco, saved_vars, liveness.
+:- import_module (lambda), termination, higher_order, accumulator, inlining.
+:- import_module deforest, dnf, magic, dead_proc_elim.
+:- import_module unused_args, lco, saved_vars, liveness.
:- import_module follow_code, live_vars, arg_info, store_alloc, goal_path.
:- import_module code_gen, optimize, export, base_type_info, base_type_layout.
:- import_module rl_gen, rl_opt, rl_out.
@@ -1009,19 +1009,19 @@
mercury_compile__maybe_higher_order(HLDS30, Verbose, Stats, HLDS32), !,
mercury_compile__maybe_dump_hlds(HLDS32, "32", "higher_order"), !,
- mercury_compile__maybe_do_inlining(HLDS32, Verbose, Stats, HLDS34), !,
+ mercury_compile__maybe_introduce_accumulators(HLDS32,
+ Verbose, Stats, HLDS33), !,
+ mercury_compile__maybe_dump_hlds(HLDS33, "33", "accum"), !,
+
+ mercury_compile__maybe_do_inlining(HLDS33, Verbose, Stats, HLDS34), !,
mercury_compile__maybe_dump_hlds(HLDS34, "34", "inlining"), !,
mercury_compile__maybe_deforestation(HLDS34,
Verbose, Stats, HLDS36), !,
mercury_compile__maybe_dump_hlds(HLDS36, "36", "deforestation"), !,
-
- mercury_compile__maybe_unused_args(HLDS36, Verbose, Stats, HLDS38), !,
- mercury_compile__maybe_dump_hlds(HLDS38, "38", "unused_args"), !,
- mercury_compile__maybe_introduce_accumulators(HLDS38,
- Verbose, Stats, HLDS39), !,
- mercury_compile__maybe_dump_hlds(HLDS39, "39", "accum"), !,
+ mercury_compile__maybe_unused_args(HLDS36, Verbose, Stats, HLDS39), !,
+ mercury_compile__maybe_dump_hlds(HLDS39, "39", "unused_args"), !,
mercury_compile__maybe_lco(HLDS39, Verbose, Stats, HLDS40), !,
mercury_compile__maybe_dump_hlds(HLDS40, "40", "lco"), !,
Index: promise/compiler/options.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/options.m,v
retrieving revision 1.276
diff -u -r1.276 options.m
--- promise/compiler/options.m 1999/12/21 09:56:38 1.276
+++ promise/compiler/options.m 1999/12/23 06:41:58
@@ -46,6 +46,7 @@
:- type option
% Warning options
---> inhibit_warnings
+ ; inhibit_accumulator_warnings
; halt_at_warn
; halt_at_syntax_errors
; warn_singleton_vars
@@ -404,6 +405,7 @@
option_defaults_2(warning_option, [
% Warning Options
inhibit_warnings - bool_special,
+ inhibit_accumulator_warnings - bool(no),
halt_at_warn - bool(no),
halt_at_syntax_errors - bool(no),
%
@@ -763,6 +765,7 @@
% warning options
long_option("inhibit-warnings", inhibit_warnings).
+long_option("inhibit-accumulator-warnings", inhibit_accumulator_warnings).
long_option("halt-at-warn", halt_at_warn).
long_option("halt-at-syntax-errors", halt_at_syntax_errors).
long_option("warn-singleton-variables", warn_singleton_vars).
@@ -1177,6 +1180,7 @@
:-
bool__not(Inhibit, Enable),
override_options([
+ inhibit_accumulator_warnings - bool(Inhibit),
warn_singleton_vars - bool(Enable),
warn_overlapping_scopes - bool(Enable),
warn_det_decls_too_lax - bool(Enable),
@@ -1420,6 +1424,9 @@
"\tThis option causes the compiler to halt immediately",
"\tafter syntax checking and not do any semantic checking",
"\tif it finds any syntax errors in the program.",
+ "--inhibit-accumulator-warnings",
+ "\tDon't warn about argument order rearrangement caused",
+ "\tby --introduce-accumulators.",
"--no-warn-singleton-variables",
"\tDon't warn about variables which only occur once.",
"--no-warn-overlapping-scopes",
Index: promise/compiler/notes/compiler_design.html
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/notes/compiler_design.html,v
retrieving revision 1.43
diff -u -r1.43 compiler_design.html
--- promise/compiler/notes/compiler_design.html 1999/12/20 18:08:39 1.43
+++ promise/compiler/notes/compiler_design.html 1999/12/23 06:42:06
@@ -534,6 +534,16 @@
value of the higher-order/type_info/typeclass_info arguments are known
(higher_order.m)
+<li> attempt to introduce accumulators (accumulator.m). This optimizes
+ procedures whose tail consists of independent associative computations
+ or independant chains of commutative computations into a tail
+ recursive form by the introduction of accumulators. If lco is turned
+ on it can also transform some procedures so that only construction
+ unifications are after the recursive call. This pass must come before
+ lco, unused_args (eliminating arguments makes it hard to relate the
+ code back to the assertion) and inlining (can make the associative
+ call disappear).
+
<li> inlining (i.e. unfolding) of simple procedures (inlining.m)
<li> pushing constraints as far left as possible (constraint.m);
@@ -563,14 +573,6 @@
<li> issue warnings about unused arguments from predicates, and create
specialized versions without them (unused_args.m); type_infos are
often unused.
-
-<li> attempt to introduce accumulators (accumulator.m). This optimizes
- procedures whose tail consists of independent associative computations
- or independant chains of commutative computations into a tail
- recursive form by the introduction of accumulators. If lco is turned
- on it can also transform some procedures so that only construction
- unifications are after the recursive call. This pass must come before
- lco.
<li> elimination of dead procedures (dead_proc_elim.m). Inlining, higher-order
specialization and the elimination of unused args can make procedures dead
Index: promise/doc/user_guide.texi
===================================================================
RCS file: /home/staff/zs/imp/mercury/doc/user_guide.texi,v
retrieving revision 1.198
diff -u -r1.198 user_guide.texi
--- promise/doc/user_guide.texi 1999/12/14 04:53:37 1.198
+++ promise/doc/user_guide.texi 1999/12/16 05:50:01
@@ -2737,6 +2737,11 @@
if it finds any syntax errors in the program.
@sp 1
+ at item --inhibit-accumulator-warnings
+Don't warn about argument order rearrangement caused by
+ at samp{--introduce-accumulators}.
+
+ at sp 1
@item --no-warn-singleton-variables
Don't warn about variables which only occur once.
Index: promise/library/list.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/list.m,v
retrieving revision 1.88
diff -u -r1.88 list.m
--- promise/library/list.m 1999/07/07 15:19:40 1.88
+++ promise/library/list.m 1999/12/09 00:47:22
@@ -72,6 +72,16 @@
% that it is semidet. Use list__remove_suffix instead.
% :- mode list__append(out, in, in) is semidet.
+ % associativity of append
+:- promise all [A, B, C, ABC]
+ (
+ ( some [AB]
+ (list__append(A, B, AB), list__append(AB, C, ABC)) )
+ <=>
+ ( some [BC]
+ (list__append(B, C, BC), list__append(A, BC, ABC)) )
+ ).
+
% list__remove_suffix(List, Suffix, Prefix):
% The same as list__append(Prefix, Suffix, List) except that
% this is semidet whereas list__append(out, in, in) is nondet.
Index: tests/general/accumulator/Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/tests/general/accumulator/Mmakefile,v
retrieving revision 1.5
diff -u -r1.5 Mmakefile
--- tests/general/accumulator/Mmakefile 1999/10/26 06:11:53 1.5
+++ tests/general/accumulator/Mmakefile 1999/11/17 13:12:44
@@ -33,10 +33,6 @@
split \
swap
- # XXX
- # Accumulators aren't introduced for -O5
- # this is just a temp workaround
-override EXTRA_MCFLAGS =
MCFLAGS = -d accum --introduce-accumulators --optimize-constructor-last-call \
--intermodule-optimization
Index: tests/general/accumulator/runtests
===================================================================
RCS file: /home/staff/zs/imp/tests/general/accumulator/runtests,v
retrieving revision 1.5
diff -u -r1.5 runtests
--- tests/general/accumulator/runtests 1999/11/02 05:27:21 1.5
+++ tests/general/accumulator/runtests 1999/11/16 07:56:05
@@ -22,10 +22,6 @@
cat *.res > .allres
if test ! -s .allres -a "$checkstatus" = 0
then
- # XXX disable these checks until we pass them
- echo "the tests in the general/accumulator directory are not fully enabled"
- exit 0
-
grep -h "% mode.*AccFrom" *hlds*acc* | sed -e 's/number//' \
| sed -e 's/ of predicate//g' > I.$$
diff -u INTRODUCED I.$$ > INTRODUCED.diff
Index: tests/warnings/Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/tests/warnings/Mmakefile,v
retrieving revision 1.7
diff -u -r1.7 Mmakefile
--- tests/warnings/Mmakefile 1999/10/26 08:47:46 1.7
+++ tests/warnings/Mmakefile 1999/12/24 02:34:01
@@ -4,7 +4,7 @@
#-----------------------------------------------------------------------------#
-PROGS= \
+ERRORCHECKONLY_PROGS= \
det_infer_warning \
double_underscore \
duplicate_call \
@@ -18,10 +18,16 @@
unused_args_test \
unused_import
+COMPILE_PROGS= \
+ arg_order_rearrangment
+
+PROGS=$(ERRORCHECKONLY_PROGS) $(COMPILE_PROGS)
+
#-----------------------------------------------------------------------------#
# some files need to be compiled with special options
+MCFLAGS-arg_order_rearrangment = --introduce-accumulators
MCFLAGS-duplicate_call = --warn-duplicate-calls
MCFLAGS-unused_args_test = --warn-unused-args
MCFLAGS-unused_import = --warn-interface-imports
@@ -36,14 +42,15 @@
#-----------------------------------------------------------------------------#
DEPENDS=$(PROGS:%=%.depend)
-ERRS= $(PROGS:%=%.err)
+ERRS= $(ERRORCHECKONLY_PROGS:%=%.err)
+CS= $(COMPILE_PROGS:%=%.c)
RESS= $(PROGS:%=%.res)
#-----------------------------------------------------------------------------#
depend: $(DEPENDS)
-check: $(ERRS) $(RESS)
+check: $(ERRS) $(CS) $(RESS)
all: $(PROGS)
Index: tests/warnings/arg_order_rearrangment.exp
===================================================================
RCS file: arg_order_rearrangment.exp
diff -N arg_order_rearrangment.exp
--- /dev/null Thu Mar 4 04:20:11 1999
+++ arg_order_rearrangment.exp Fri Dec 24 13:02:09 1999
@@ -0,0 +1,9 @@
+arg_order_rearrangment.m:004: The predicate `arg_order_rearrangment:r/2'
+arg_order_rearrangment.m:010: warning: the call to predicate
+arg_order_rearrangment.m:010: `arg_order_rearrangment:app/3' has had the
+arg_order_rearrangment.m:010: location of the variables R0 and V_7 swapped
+arg_order_rearrangment.m:010: to allow accumulator introduction.
+arg_order_rearrangment.m:004: Please ensure that these argument
+arg_order_rearrangment.m:004: rearrangements do not introduce performance
+arg_order_rearrangment.m:004: problems. These warnings can be suppressed by
+arg_order_rearrangment.m:004: `--inhibit-accumulator-warnings'.
Index: tests/warnings/arg_order_rearrangment.m
===================================================================
RCS file: arg_order_rearrangment.m
diff -N arg_order_rearrangment.m
--- /dev/null Thu Mar 4 04:20:11 1999
+++ arg_order_rearrangment.m Fri Dec 24 13:47:21 1999
@@ -0,0 +1,26 @@
+# For accumulators to be introduced into r, R0 and [H] must have their
+# order swapped. The compiler should warn the user that this may have
+# performance implications (a good one in this case).
+:- module arg_order_rearrangment.
+:- interface.
+:- import_module list.
+:- pred r(list(T)::in, list(T)::out) is det.
+:- implementation.
+
+r([], []).
+r([H|T], R) :-
+ r(T, R0),
+ app(R0, [H], R).
+
+:- promise all [A, B, C, ABC]
+ (
+ (some [AB] (app(A, B, AB), app(AB, C, ABC)))
+ <=>
+ (some [BC] (app(B, C, BC), app(A, BC, ABC)))
+ ).
+
+:- pred app(list(T)::in, list(T)::in, list(T)::out) is det.
+
+app([], Ys, Ys).
+app([X|Xs], Ys, [X|Zs]) :-
+ app(Xs, Ys, Zs).
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to: mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions: mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------
More information about the developers
mailing list