[m-dev.] for review: type specialization [1]
Simon Taylor
stayl at cs.mu.OZ.AU
Thu Feb 18 16:14:09 AEDT 1999
Hi Fergus,
This relative diff (full diff for reference_manual.texi) addresses
your concerns, mostly changing the format of type subsitututions.
Thanks,
Simon.
===================================================================
RCS file: RCS/higher_order.m,v
retrieving revision 1.1
diff -u -r1.1 higher_order.m
--- higher_order.m 1999/02/18 03:19:16 1.1
+++ higher_order.m 1999/02/18 03:26:24
@@ -901,6 +901,10 @@
Result = no_request
).
+ % If `--typeinfo-liveness' is set, specializing type `T' to `list(U)'
+ % requires passing in the type-info for `U'. This predicate
+ % works out which extra variables to pass in given the argument
+ % list for the call.
:- pred compute_extra_typeinfos(higher_order_info::in, list(prog_var)::in,
list(prog_var)::out, list(type)::out) is det.
===================================================================
RCS file: RCS/make_hlds.m,v
retrieving revision 1.1
diff -u -r1.1 make_hlds.m
--- make_hlds.m 1999/02/18 03:19:02 1.1
+++ make_hlds.m 1999/02/18 04:39:52
@@ -988,6 +988,7 @@
;
report_subst_existq_tvars(PredInfo0, Context,
SubExistQVars),
+ io__set_exit_status(1),
{ module_info_incr_errors(ModuleInfo0, ModuleInfo) },
{ Types = [] },
{ ClassContext = constraints([], []) },
@@ -995,7 +996,13 @@
)
;
report_non_ground_subst(PredInfo0, Context),
- { module_info_incr_errors(ModuleInfo0, ModuleInfo) },
+ globals__io_lookup_bool_option(halt_at_warn, Halt),
+ ( { Halt = yes } ->
+ { module_info_incr_errors(ModuleInfo0, ModuleInfo) },
+ io__set_exit_status(1)
+ ;
+ { ModuleInfo = ModuleInfo0 }
+ ),
{ ExistQVars = [] },
{ Types = [] },
{ ClassContext = constraints([], []) },
@@ -1006,6 +1013,7 @@
report_unknown_vars_to_subst(PredInfo0, Context,
TVarSet0, UnknownVarsToSub),
{ module_info_incr_errors(ModuleInfo0, ModuleInfo) },
+ io__set_exit_status(1),
{ ExistQVars = [] },
{ Types = [] },
{ ClassContext = constraints([], []) },
@@ -1042,10 +1050,11 @@
report_non_ground_subst(PredInfo0, Context) -->
report_pragma_type_spec(PredInfo0, Context),
- io__write_string(" error: the substitution does not make the\n"),
- io__nl,
+ io__write_string(" warning: the substitution does not make the\n"),
prog_out__write_context(Context),
- io__write_string(" substituted types ground.\n").
+ io__write_string(" substituted types ground.\n"),
+ prog_out__write_context(Context),
+ io__write_string(" The declaration will be ignored.\n").
:- pred report_unknown_vars_to_subst(pred_info, prog_context, tvarset,
list(tvar), io__state, io__state).
===================================================================
RCS file: RCS/mercury_to_mercury.m,v
retrieving revision 1.1
diff -u -r1.1 mercury_to_mercury.m
--- mercury_to_mercury.m 1999/02/18 03:26:53 1.1
+++ mercury_to_mercury.m 1999/02/18 04:39:52
@@ -2220,10 +2220,9 @@
io__write_int(Arity)
),
- io__write_string(", ["),
- list__foldl(mercury_output_type_subst(VarSet), Subst),
-
- io__write_string("], "),
+ io__write_string(", ("),
+ io__write_list(Subst, ", ", mercury_output_type_subst(VarSet)),
+ io__write_string("), "),
mercury_output_bracketed_sym_name(SpecName, not_next_to_graphic_token),
io__write_string(").\n").
@@ -2233,7 +2232,7 @@
mercury_output_type_subst(VarSet, Var - Type) -->
mercury_output_var(Var, VarSet, no),
- io__write_string(" - "),
+ io__write_string(" = "),
mercury_output_term(Type, VarSet, no).
%-----------------------------------------------------------------------------%
===================================================================
RCS file: RCS/prog_io_pragma.m,v
retrieving revision 1.1
diff -u -r1.1 prog_io_pragma.m
--- prog_io_pragma.m 1999/02/18 03:26:53 1.1
+++ prog_io_pragma.m 1999/02/18 04:51:42
@@ -390,10 +390,8 @@
(
ArityOrModesResult = ok(arity_or_modes(PredName,
Arity, MaybePredOrFunc, MaybeModes)),
- convert_list(TypeSubnTerm, convert_type_spec_pair,
- TypeSubnResult),
- (
- TypeSubnResult = ok(TypeSubn),
+ conjunction_to_list(TypeSubnTerm, TypeSubnList),
+ ( list__map(convert_type_spec_pair, TypeSubnList, TypeSubn) ->
( MaybeName = yes(SpecializedName0) ->
Counter = Counter0,
SpecializedName = SpecializedName0
@@ -427,7 +425,6 @@
SpecializedName, Arity, MaybePredOrFunc,
MaybeModes, TypeSubn, VarSet)))
;
- TypeSubnResult = error(_, _),
Counter = Counter0,
Result = error(
"expected type substitution in `pragma type_spec(...)' declaration",
@@ -1104,7 +1101,7 @@
:- pred convert_type_spec_pair(term::in, pair(tvar, type)::out) is semidet.
convert_type_spec_pair(Term, TypeSpec) :-
- Term = term__functor(term__atom("-"), [TypeVarTerm, SpecTypeTerm0], _),
+ Term = term__functor(term__atom("="), [TypeVarTerm, SpecTypeTerm0], _),
TypeVarTerm = term__variable(TypeVar0),
term__coerce_var(TypeVar0, TypeVar),
term__coerce(SpecTypeTerm0, SpecType),
Index: reference_manual.texi
===================================================================
RCS file: /home/staff/zs/imp/mercury/doc/reference_manual.texi,v
retrieving revision 1.120
diff -u -r1.120 reference_manual.texi
--- reference_manual.texi 1999/02/08 22:42:51 1.120
+++ reference_manual.texi 1999/02/18 05:06:14
@@ -3201,6 +3201,8 @@
* Impurity:: Users can write impure Mercury code
* Inlining:: Pragmas can be used to suggest or prevent
procedure inlining.
+* Type specialization:: Produce specialized versions of polymorphic
+ predicates.
* Obsolescence:: Library developers can declare old versions
of predicates or functions to be obsolete.
* Source file name:: The @samp{source_file} pragma and
@@ -4422,6 +4424,83 @@
simply for performance concerns (inlining can cause unwanted code bloat
in some cases) or to prevent possibly dangerous inlining when using
low-level C code.
+
+ at node Type specialization
+ at section Type specialization
+
+The overhead of polymorphism can in some cases be significant, especially
+where polymorphic predicates make heavy use of class method calls or the
+built-in unification and comparison routines. To avoid this, the programmer
+can suggest to the compiler that a specialized version of a procedure should
+be created for a specific set of argument types.
+
+A declaration of the form
+
+ at example
+:- pragma type_spec(@var{Name}/@var{Arity}, @var{Subst}).
+:- pragma type_spec(@var{Name}(@var{Modes}), @var{Subst}).
+ at end example
+
+ at noindent
+suggests to the compiler that a specialized version of the named predicate
+or function should be created with the type substitution given by
+ at var{Subst} applied to the argument types. The second form of the declaration
+only suggests specialization of the specified mode of the predicate.
+
+The substitution is written as a conjunction of bindings of the form
+ at w{@samp{@var{TypeVar} = @var{Type}}}, for example @w{@samp{K = int}} or
+ at w{@samp{(K = int, V = list(int))}}.
+
+The declarations
+
+ at example
+:- pred map__lookup(map(K, V), K, V).
+:- pragma type_spec(map__lookup/3, K = int).
+ at end example
+
+ at noindent
+give a hint to the compiler that a version of @samp{map__lookup/3} should
+be created for integer keys.
+
+An implementation is free to ignore @samp{pragma type_spec} declarations.
+
+ at menu
+* When to use type specialization::
+* Implementation specific details::
+ at end menu
+
+ at node When to use type specialization
+ at subsection When to use type specialization
+
+The set of types for which a predicate or function should be specialized is
+best determined by profiling your application. Overuse of type specialization
+will result in code bloat.
+
+Type specialization of predicates or functions which
+unify or compare polymorphic variables is most effective when
+the specialized types are built-in types such as @samp{int}, @samp{float}
+and @samp{string}, or enumeration types, since their unification and
+comparison procedures are small and can be inlined.
+
+Predicates or functions which make use of typeclass method calls
+may also be candidates for specialization. Again, this is most effective
+when the called typeclass methods are small enough to be inlined.
+
+ at node Implementation specific details
+ at subsection Implementation specific details
+
+The Melbourne Mercury compiler performs user-requested type specializations
+when invoked with @samp{--user-guided-type-specialization}, which is enabled
+at @samp{-O2}.
+
+The replacement types must be ground. A substitution such as
+ at w{@samp{T = list(U)}} is invalid. The compiler will warn about
+such substitutions, and will ignore the request for specialization.
+This restriction may be lifted in the future.
+ at c The main reason for this restriction is that it is tricky to ensure that
+ at c any extra typeclass_infos that may be needed are ordered the same way in
+ at c different modules. The efficiency gain from replacing a type variable with
+ at c a non-ground type will usually be pretty small anyway.
@node Obsolescence
@section Obsolescence
More information about the developers
mailing list