[m-rev.] for review: new termination analyser (part 5 of 6)
Mark Brown
mark at cs.mu.OZ.AU
Sat Apr 2 03:30:56 AEST 2005
On 24-Mar-2005, Julien Fischer <juliensf at cs.mu.OZ.AU> wrote:
>
> +%-----------------------------------------------------------------------------%
> Index: compiler/term_constr_errors.m
> ===================================================================
> RCS file: compiler/term_constr_errors.m
> diff -N compiler/term_constr_errors.m
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ compiler/term_constr_errors.m 9 Mar 2005 03:43:17 -0000
> +%-----------------------------------------------------------------------------%
> +%
> +% Termination 2 Errors
> +%
> +
> +% The termination errors are all in reference to possible non-termination.
> +% While it is possible for pass 1 to go amiss the worst that will happen
> +% (barring an abnormal abort) is that the size of the arguments will be
> +% unconstrained.
> +
> +:- type termination2_error
> + ---> imported_pred
> + % Termination could not be proved because
> + % it depends upon information from another
> + % module and that information is not
> + % available.
> +
> + ; can_loop_proc_called(pred_proc_id, pred_proc_id)
> + % Termination could not be proved because
> + % the procedure called another procedure
> + % that may not terminate.
> +
> + ; cond_not_satisfied
> + % Termination could not be proved because
> + % no set of decreasing argument could e found.
s/could e/could be/
> Index: compiler/term_constr_fixpoint.m
> ===================================================================
> RCS file: compiler/term_constr_fixpoint.m
> diff -N compiler/term_constr_fixpoint.m
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ compiler/term_constr_fixpoint.m 24 Mar 2005 04:20:56 -0000
> +%-----------------------------------------------------------------------------%
> +
> + % Calculate the next approximation to the argument size constraints.
> + %
> + % ChangeFlag is `yes' if the constraints for any procedure in the SCC
> + % have changed since the previous iteration.
> + %
> +:- pred do_fixpoint_calculation(fixpoint_options::in, list(pred_proc_id)::in,
> + int::in, term2_errors::out, module_info::in, module_info::out,
> + io::di, io::uo) is det.
The comment isn't right, since this predicate does the full calculation
rather than just one iteration, and also there is no ChangeFlag.
> +:- func fixpoint_options_init(widening, int) = fixpoint_options.
The arguments to this function should be documented.
> +%------------------------------------------------------------------------------%
> +%
> +% Perform a fixpoint iteration on the AR.
This does the full calculation, right? The next section of code does
an iteration.
> + %
> + % Look up the constraints obtained during the previous
> + % iteration.
> + %
> + ArgSizeInfo = lookup_proc_constr_arg_size_info(ModuleInfo, PPId),
> + %
> + % NOTE: `!.Polyhedron' is the set of constraints obtained by
> + % *this* iteration. `OldPolyhedron' is the set of constraints
> + % obtained by the *previous* iteration -- which may in fact
> + % be `empty' (false).
> + %
> + (
> + % If there were no constraints for the procedure then
> + % we are at the beginning of the analysis.
> + %
> + ArgSizeInfo = no,
> + OldPolyhedron = polyhedron.empty
> + ;
> + ArgSizeInfo = yes(SizeInfo),
> + SizeInfo = OldPolyhedron
That would be easier to understand if OldPolyhedron was on the left.
> + %
> + % Set any zero_vars in the constraints
> + % to zero (ie. delete the terms). We need
> + % to do this when a polymorphic arguments
s/when a/when/
> +%------------------------------------------------------------------------------%
> +%
> +% Predicates for handling disjunctions.
> +%
> +
> + % This version computes the convex hull linearly.
> + % That is, ( A ; B ; C ; D) is processed as:
> + %
> + % ((((identity \/ A ) \/ B ) \/ C ) \/ D)
> + %
> +:- pred traverse_abstract_disj_linearly(abstract_goals::in,
> + size_vars::in, fixpoint_info::in, polyhedron::in, polyhedron::out)
> + is det.
> +
> +traverse_abstract_disj_linearly(Goals, Locals, Info, !Polyhedron) :-
> + list.foldl(traverse_abstract_disjunct_linearly(Info, Locals),
> + Goals, polyhedron.empty, ConvexUnion),
> + polyhedron.intersection(ConvexUnion, !Polyhedron).
> +
> +:- pred traverse_abstract_disjunct_linearly(fixpoint_info::in,
> + size_vars::in, abstract_goal::in, polyhedron::in, polyhedron::out)
> + is det.
Why not call this "traverse_abstract_disj_linearly_2"?
> + % This assumes that the operation in question is associative and
> + % commutative.
> + %
> + :- func pairwise_map(func(T, T) = T, list(T)) = T.
No biggie, but this bears more resemblance to a "fold" than to a "map".
> +:- func test_fixpoint(polyhedron, polyhedron, size_varset) = bool.
> +
> +test_fixpoint(NewPoly, OldPoly, Varset) = ChangeFlag :-
> + %
> + % Constraints from this iteration.
> + %
> + NewConstraints = polyhedron.non_false_constraints(NewPoly),
> + %
> + % Constraints from previous iteration.
> + %
> + OldConstraints = polyhedron.non_false_constraints(OldPoly),
> + UnchangedConstraints = list.filter(entailed(Varset, NewConstraints),
> + OldConstraints),
> + ( if list.same_length(OldConstraints, UnchangedConstraints)
> + then ChangeFlag = no
> + else ChangeFlag = yes
> + ).
How about:
(
some [OldConstraint] (
member(OldConstraint, OldConstraints),
\+ entailed(Varset, NewConstraints, OldConstraint)
)
->
ChangeFlag = yes
;
ChangeFlag = no
)
This would perform a (green) cut at the first OldConstraint that was not
entailed, rather than checking all of them.
> Index: compiler/term_constr_initial.m
> ===================================================================
> RCS file: compiler/term_constr_initial.m
> diff -N compiler/term_constr_initial.m
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ compiler/term_constr_initial.m 24 Mar 2005 04:19:36 -0000
> +%----------------------------------------------------------------------------%
> +%
> +% Process each predicate and set the termination property
> +%
> +
> +% Sets termination to `cannot_loop' if:
> +% - there is a `terminates' pragma defined for the predicate.
> +% - there is a `check_termination' pragma defined for the predicate
> +% *and* the compiler is not currently generating the intermodule
> +% optimization file.
> +% - the predicate is builtin or compiler generated. (These are assumed
> +% to terminate.
Close parenthesis.
> +%----------------------------------------------------------------------------%
> +%
> +% Set the argument size constraints for imported procedures.
> +%
> +
> +% When interargument size constraints are imported from other modules there
> +% are two parts. The first of the these is a list of ints. Each int
> +% represents one of a procedures arguments (including typeinfo related ones).
s/procedures/procedure's/
> +:- pred process_imported_proc(proc_id::in, proc_table::in, proc_table::out)
> + is det.
> +
> +process_imported_proc(ProcId, !ProcTable) :-
> + some [!ProcInfo] (
> + !:ProcInfo = !.ProcTable ^ det_elem(ProcId),
> + proc_info_get_termination2_info(!.ProcInfo, TermInfo0),
It would be better to test for import_headvarids = yes(HeadVarIds) here
rather than below...
> + process_imported_term_info(!.ProcInfo, TermInfo0, TermInfo),
> + proc_info_set_termination2_info(TermInfo, !ProcInfo),
> + svmap.det_update(ProcId, !.ProcInfo, !ProcTable)
...because that would save updating the proc_info and proc_table
unnecessarily.
> +:- pred set_compiler_gen_terminates(pred_info::in, list(proc_id)::in,
> + pred_id::in, module_info::in, proc_table::in, proc_table::out)
> + is semidet.
> +
> +set_compiler_gen_terminates(PredInfo, ProcIds, PredId, ModuleInfo,
> + !ProcTable) :-
> + ( hlds_pred.pred_info_is_builtin(PredInfo) ->
> + set_builtin_terminates(ProcIds, PredId, PredInfo, ModuleInfo,
> + !ProcTable)
> + ;
> + (
> + Name = pred_info_name(PredInfo),
> + Arity = pred_info_orig_arity(PredInfo),
> + special_pred_name_arity(SpecPredId0, Name, Arity),
> + ModuleName = pred_info_module(PredInfo),
> + any_mercury_builtin_module(ModuleName)
> + ->
> + SpecialPredId = SpecPredId0
> + ;
> + pred_info_get_origin(PredInfo, PredOrigin),
> + PredOrigin = special_pred(SpecialPredId - _)
> + )
> + ->
> + set_generated_terminates(ProcIds, SpecialPredId, ModuleInfo,
> + !ProcTable)
> + ;
> + fail
> + ).
The above code needs some reformatting.
> + % Sets up the arg_size an termination info for those special preds
s/an/and/
To be continued...
--------------------------------------------------------------------------
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