[m-rev.] for review: extend mutual tail rec optimization to functions
Julien Fischer
jfischer at opturion.com
Wed Sep 13 14:09:25 AEST 2017
On Tue, 12 Sep 2017, Zoltan Somogyi wrote:
> For review by Julien, since this builds on a diff that he reviewed,
> so he is in the best position to understand it quickly.
>
> The attached file TSCC_PROC shows that stage2 of a bootcheck
> contains 23 optimized mutually recursive functions, as well as
> 270 optimized mutually recursive predicates.
>
> The approach implemented in this diff should work to optimize
> mutual tail recursion in Java and C# as well as C. It is not yet
> turned on for those languages, because I can't test it yet.
...
> Extend mutual tail recursion optimization to functions.
...
> compiler/ml_args_util.m:
> When computing the information needed for tscc arguments, don't assume
> that there are no copy-out output arguments. Instead, compute the
> information ml_proc_gen.m needs to handle them. This means returning
> a full function signature (including return values), the list of rvals
> to return, and the list of pre-return assignment statements.
>
> Simplify the code of ml_append_return_statement. Since ml_proc_gen.m
> now computes its own return statements (based on the information mentioned
> in the previous paragraph) back to handle just the situation it was
There are some words missing there.
> originally designed for: simple procedure bodies that are *not* parts
> of TSCCs. Simplify its code also by requiring its callers to give it
> the return values as rvals, not lvals, because the callers can give it
> the return values in this form just as easily, and it is more efficient,
> since it lets us avoid the construction of a list.
>
> compiler/ml_proc_gen.m:
> Let det functions be part of TSCCs. Handle their return values as described
> above. Handle the construction of return statements for procedure bodies
> in TSCCs separately from return statements in standalone procedures.
>
> compiler/ml_closure_gen.m:
> Conform to the changes in ml_args_util.m.
> diff --git a/compiler/ml_args_util.m b/compiler/ml_args_util.m
> index 82200d7..a32f464 100644
> --- a/compiler/ml_args_util.m
> +++ b/compiler/ml_args_util.m
...
> @@ -179,30 +179,42 @@
> % The value returned in TsccInLocalVarDefns will be a local var definition
> % of each variable in TsccInArgs. This is used to define those variables
> % in copies of the TSCC code that are *not* for this procedure.
> + % (This is we ensure that each lvn_tscc_proc_input_var will be defined
> + % by exactly one of TsccInLocalVarDefns and TsccInArgs in each copy.)
> %
> - % The value returned in TsccArgs is a list of all the arguments of the
> - % procedure, both input and output, in declaration order. This will be
> - % the argument list of the copy of the TSCC for this procedure,
> - % and thus it will define the lvn_tscc_proc_input_vars in that copy.
> - % (Thus the lvn_tscc_proc_input_vars will be defined by exactly one of
> - % TsccInLocalVarDefns and TsccInArgs in each copy.)
> + % The value returned in FuncParams will be the signature of the function.
> + % The function's arguments will be a list of all the input arguments and
> + % all the byref output arguments of the procedure, in declaration order;
> + % the returns will be a list of all the copied-out output arguments,
> + % again in declaration order, possibly preceded by a success indicator
> + % (if the code model is model_semi). ReturnRvals will contain the
> + % the rvals representing all the copied-out output arguments, which should
> + % all be returned together in a retun statement. These will consist
> + % of the copied-out output arguments' lvn_tscc_output_vars, again
> + % possibly preceded by a success indicator.
> %
> % Each procedure's part in the TSCC defines local MLDS variables for each
> - % argument, both input and output (returned in OwnLocalVarDefns), and
> - % its code starts by copying the values of each lvn_tscc_proc_input_var
> - % *and* lvn_tscc_output_var to the local var (from OwnLocalVarDefns)
> - % corresponding to them. For input argument, this copies the value;
> - % for output arguments, this copies the address where the argument's value
> - % should be put. These assignments are returned in CopyTsccToOwnStmts.
> - %
> -:- pred ml_gen_tscc_arg_params(module_info::in, prog_context::in,
> - proc_id_in_tscc::in, prog_varset::in,
> + % argument, both input and output (returned in OwnLocalVarDefns). Its code
> + % starts by copying the values of each lvn_tscc_proc_input_var
> + % and each byref lvn_tscc_output_var to the corresponding local var.
> + % For input argument, this copies the value; for byref output arguments,
s/input argument/input arguments/
> + % this copies the address where the argument's value should be put.
> + % These assignments are returned in CopyTsccToOwnStmts. This will be
> + % followed by the code of the procedure body, which in turn will be
> + % followed by CopyOwnToTsccStmts, which will copy each of the procedure's
> + % copied-out output vars (if there are any) to its corresponding
> + % lvn_tscc_output_var. After this, a return statement constructed around
> + % ReturnRvals will then return these (and maybe a success indication)
> + % to the caller.
...
> diff --git a/compiler/ml_proc_gen.m b/compiler/ml_proc_gen.m
> index ae5316d..a90423e 100644
> --- a/compiler/ml_proc_gen.m
> +++ b/compiler/ml_proc_gen.m
...
> @@ -761,22 +765,47 @@ ml_gen_tscc(ModuleInfo, Target, ConstStructMap, _SCCEntryPredProcIds,
> % hoisted-out definitions. Therefore, until we teach ml_elim_nested.m
> % not to do that, we abandon the optimization of mutually recursive
> % tail calls in the presence of such nested function definitions.
> + %
> + % Caveat 3.
> + % The code in mark_tail_calls.m looks for tail calls by looking
> + % at the argument lists of procedures. These argument lists treat
> + % a variable representing the result of functions the same as
> + % a variable representing the last argument of a predicate.
> + % On the other hand, on the C backend, the MLDS uses two *different*
> + % mechanisms to return these arguments; it returns function results
> + % via return statements, while it uses pass-by-reference for all
> + % other output arguments. Currently, ml_gen_tscc_trial handles this
> + % by returning CanGenerateTscc = can_not_generate_code_for_tscc
> + % if the procedures in the TSCC it is given don't all have the same
> + % vector of return values.
> + % XXX When a TSCC contains both predicates and functions, the two
> + % must present different signatures to their callers *outside* the
> + % TSCC, because those callers expect those different signatures.
> + % However, *inside* the TSCC, we could generate code that ignores
> + % the distinction, the obvious way of doing that being to use
> + % the tail call version of the caling convention intended for
s/caling/calling/
> + % predicates for all intra-TSCC tail calls. However, using different
> + % conventions for intra- and inter-TSCC parameter passing would
> + % complicate the code both here and in ml_args_util.m, and for now
> + % at least, I (zs) don't see that the potential benefits justify
> + % the costs.
> + %
...
> @@ -997,8 +1042,9 @@ separate_mutually_recursive_procs(NoMutualTailRecProcs,
>
> % Argument definitions for the TSCC variables for all
> % the arguments of the procedure, both input and output,
> - % in their original order.
> - ppiai_tscc_args :: list(mlds_argument),
> + % in their original order, and the types of the returned
> + % arguments.
> + ppiai_tscc_func_params :: mlds_func_params,
>
> % The tscc variables for the input arguments of procedure i
> % in the TSCC will be defined
> @@ -1009,23 +1055,39 @@ separate_mutually_recursive_procs(NoMutualTailRecProcs,
> % - at the top of the body of the MLDS function,
> % if the MLDS function is for procedure j with i != j.
> %
> - % The tscc variables for the output arguments will always
> - % be defined in the argument list of the MLDS function.
> + % The tscc variables for the byref output arguments will
Why has tscc suddenly become lowercase here? It was uppercase above.
> + % always be defined in the argument list of the MLDS function.
> + % The tscc variables for the copied-out output arguments will
> + % always be defined at the top of the body of the MLDS
> + % function.
The diff looks fine otherwise.
Julien.
More information about the reviews
mailing list