[m-rev.] for review: [CTGC] generate optimised versions, reuse pragmas

Nancy Nancy.Mazur at cs.kuleuven.ac.be
Wed Jun 7 19:08:00 AEST 2006


Julien Fischer wrote:
> On Tue, 6 Jun 2006, Nancy Mazur wrote:
> 
>> Hi,
>>
>> for anybody to review....
>>
>> I've got one problem with the change below which also contains the mechanism
>> to output structure_reuse pragma's, as well as reading them back in. Each
>> structure reuse pragma is related to a procedure. It dictates the
>> conditions which a caller of this procedure needs to meet in order to
>> safely replace the original call by a call to the optimised version of that
>> procedure. This means that for each procedure, we create a separate (optimised)
>> version (if optimisations are possible of course) with a compiler-generated
>> name. This name is generated using the function:
>>
>> 	generate_reuse_name(module_info, pred_proc_id) = reuse_name.
>>
>> defined in structure_reuse.split,
>> which uses the predicate
>>
>> 	prog_util.make_pred_name_with_context/7
>>
>> The problem is that this generates a name with a whole bunch of "__", and of
>> course, once you print this name out, and read it back in, you get a sym_name
>> with the strangest set of qualifiers.
> 
> Why (and where) do you need to print it out and read it back in?  In the .opt
> or .trans_opt files?  I would have thought that the presence of a reuse pragma
> in those files would be sufficient to indicate the presence of optimized
> versions of the procedures.

Yes, I was coming to exactly the same conclusion. I'll remove the reuse 
name altogether from the pragma.

[...]

> I don't see why the reuse pragmas need to include the name of the optimised
> version at all.  It ought to be enough to know what the name of the original
> procedure, what the reuse description was and that an optimised version
> exists.  The importing module ought to be able to reconstruct the name of the
> optimised version given this information.
> 
> (I think we do a similar thing with the specialized versions created by
> unused argument analysis (compiler/unused_args.m) - so you might want
> to have a look there.)

I'll have a look there.


>> Estimated hours taken: 15
>> Branches: main
>>
>> Create optimised versions for all the procedures in which possibilities for
>> structure reuse are detected.
> 
> s/in which/for which/
> 
> That's potentially going to be a rather large number of them.

I don't remember that that was really an issue in the benchmarks I've 
done.. but this should be checked yes.


>> Put the mechanism in place to generate reuse
>> pragma's, and to parse them back in.
> 
> s/pragma's/pragmas/
> 
> 
> 
>> compiler/add_pragma.m:
>> compiler/make_hlds_passes.m:
>> compiler/mercury_to_mercury.m:
>> compiler/prog_ctgc.m:
>> compiler/prog_io_pragma.m:
>> compiler/structure_reuse.analysis.m:
>> compiler/trans_opt.m:
>> 	Add the mechanism to output and parse the structure_reuse pragma's.
>>
> 
> s/pragma's/pragmas/
> 
>> compiler/hlds_module.m:
>> 	Simplify the type structure_reuse_info.
>>
>> compiler/hlds_pred.m:
>> 	Add structure sharing information at the level of each individual
>> 	procedure. This information consists of a description of any reuse
>> 	conditions that have been derived for that procedure.
>>
>> compiler/prog_item.m:
>> compiler/prog_data.m:
>> 	Add types for the public representation of reuse conditions.
>> 	(remove the previous name "reuse_tuple", which simply does not sound
>> 	adequate).
>>
>> compiler/prog_type.m:
>> 	Add functions to remove all typeinfo-vars from a
>> 	given list (resp. set) of vars.
>>
>> compiler/structure_reuse.domain.m:
>> 	Conversion procedures between the public and private representation
>> 	for structure reuse conditions.
>>
>> compiler/structure_reuse.indirect.m:
>> 	Do not try to replace call information even when you know the
>> 	pred_proc_id of the reuse version of that call (which is the case for
>> 	imported procedures with reuse). It is more consistent
>> 	to do this at the same time when all the other conversions are done,
>> 	i.e. when generating the optimised versions of the procedures with
>> 	reuse (even with unconditional reuse).
>>
>> compiler/structure_reuse.lbu.m:
>> compiler/structure_reuse.lfu.m:
>> 	Make sure that no lbu/lfu information regarding typeinfo-vars is
>> 	recorded. These variables are irrelevant for the analysis. On the
>> 	contrary, keeping these variables may cause errors:
>> 	the generated (reuse) pragma's may end up containing these
>> 	typeinfo-vars, when reading these pragma's back in, it becomes
>> 	troublesome to match them with the corresponding predicate signatures,
>> 	as these signatures do not contain such typeinfo-headvars.
>>
>> compiler/structure_reuse.analysis.m:
>> compiler/structure_reuse.m:
>> compiler/structure_reuse.split.m:
>> 	Create optimised versions for the procedures for which
>> 	reuse was detected.
>> 	(structure_reuse.split.m = new file)
>>
> 
> Why is it called split?  (That doesn't immediately mean anything to me.)

I'll use your suggestion of structure_reuse.versions.


>> compiler/structure_sharing.analysis.m:
>> 	Add some documentation.
>>
>>
>>
>>
>> Index: compiler/add_pragma.m
>> ===================================================================
>> RCS file: /home/mercury1/repository/mercury/compiler/add_pragma.m,v
>> retrieving revision 1.33
>> diff -u -d -r1.33 add_pragma.m
>> --- compiler/add_pragma.m	5 Jun 2006 02:26:06 -0000	1.33
>> +++ compiler/add_pragma.m	6 Jun 2006 13:31:22 -0000
>> @@ -56,6 +56,11 @@
>>      maybe(structure_sharing_domain)::in, prog_context::in,
>>      module_info::in, module_info::out, io::di, io::uo) is det.
>>
>> +:- pred add_pragma_structure_reuse(pred_or_func::in, sym_name::in,
>> +    list(mer_mode)::in, list(prog_var)::in, list(mer_type)::in,
>> +    maybe(structure_reuse_domain)::in, maybe(sym_name)::in, prog_context::in,
>> +    module_info::in, module_info::out, io::di, io::uo) is det.
>> +
>>      % module_add_pragma_import:
>>      %
>>      % Handles `pragma import' declarations, by figuring out which predicate
>> @@ -1227,6 +1232,99 @@
>>          %   module_info_incr_errors(!ModuleInfo)
>>      ).
>>
>> +add_pragma_structure_reuse(_PredOrFunc, _SymName, _ModeList, _HeadVars,
>> +        _Types, no, _MaybeReusePredName, _Context, !ModuleInfo, !IO).
>> +add_pragma_structure_reuse(PredOrFunc, SymName, ModeList, HeadVars,
>> +        Types, yes(ReuseDomain), MaybeReusePredName,
>> +        Context, !ModuleInfo, !IO):-
>> +    module_info_get_predicate_table(!.ModuleInfo, Preds),
>> +    list.length(ModeList, Arity),
>> +    (
>> +        predicate_table_search_pf_sym_arity(Preds, is_fully_qualified,
>> +            PredOrFunc, SymName, Arity, PredIds),
>> +        PredIds = [_ | _]
>> +    ->
>> +        ( PredIds = [PredId] ->
>> +            module_info_preds(!.ModuleInfo, PredTable0),
>> +            map.lookup(PredTable0, PredId, PredInfo0),
>> +            pred_info_get_procedures(PredInfo0, ProcTable0),
>> +            map.to_assoc_list(ProcTable0, ProcList),
>> +            (
>> +                get_procedure_matching_declmodes(ProcList, ModeList,
>> +                    !.ModuleInfo, ProcId)
>> +            ->
>> +                map.lookup(ProcTable0, ProcId, ProcInfo0),
>> +
>> +                % Rename headvars/types to those used in the proc_info.
>> +                proc_info_get_headvars(ProcInfo0, ProcHeadVars),
>> +
>> +                % As the HeadVars recorded in the pragma may contain additional
>> +                % vars (e.g. typeinfos), and in the same time ProcHeadVars does
>> +                % not, make sure to remove all TypeInfo-vars from HeadVars,
>> +                % the same for the list Types.
>> +                Diff = list.length(HeadVars) - list.length(ProcHeadVars),
>> +                (
>> +                    list.drop(Diff, HeadVars, RemHeadVars0),
>> +                    list.drop(Diff, Types, RemTypes0)
>> +                ->
>> +                    RemHeadVars = RemHeadVars0,
>> +                    RemTypes = RemTypes0
>> +                ;
>> +                    unexpected(this_file, "Impossible situation.")
>> +                ),
> 
> In my experience this sort of things tends to be highly breakable.  The
> approach I took with the with termination2_info pragmas was to delay
> further processing of the pragam until after the polymorphism pass has
> been run (in fact until the beginning of the termination 2 pass - see
> term_constr_initial.preprocess_module/4).
> 
> I think that kind of approach would also be better here, i.e. delay
> further processing of the structure_reuse pragmas until the information
> in them is actually needed.

I'll have a look at how it is done with termination2_info pragmas... On 
the reuse branch we also took the approach of delaying the processing, 
yet that involved some other ugly bits...

I'll have a look.

>>          list.foldl(term_constr_main.output_pred_termination2_info(Module),
>>              PredIds, !IO),
>>
>> +        % XXX I have a strong feeling that also writing termination info and
>> +        % exception information should be limited to those pred_ids that do not
>> +        % correspond to compiler generated reuse versions of other predicates.
>> +        %
> 
> Yes, you should exclude the reuse versions.  (Since reuse should not affect
> the termination/exception properties of a procedure, if we want to know
> what they are we should just look up the information for the original
> version.)

Ok!

Nancy

Disclaimer: http://www.kuleuven.be/cwis/email_disclaimer.htm

--------------------------------------------------------------------------
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