mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 09:23:44 +00:00
compiler/unused_args_analysis.m:
New module containing the parts of the old unused_args.m
that deal with the intermodule analysis framework.
compiler/unused_args_base_ops.m:
New module containing the parts of the old unused_args.m
that define and operate on the main data structure we use
to find out which variables are unused.
compiler/unused_args_optimize.m:
New module containing the parts of the old unused_args.m
that "optimize out" unused arguments.
compiler/unused_args_warn_pragma.m:
New module containing the parts of the old unused_args.m
that generate warnings about unused arguments, and that generate
unused_args pragmas for .opt files. The module contains both
because they share the same test for whether we want to ignore
any unused arguments in a predicate.
compiler/unused_args.m:
Delete the moved code.
compiler/transform_hlds.m:
compiler/notes/compiler_design.html:
Include and document the new modules.
compiler/mercury_compile_middle_passes.m:
compiler/mmc_analysis.m:
Conform to the changes above.
1652 lines
68 KiB
Mathematica
1652 lines
68 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2009-2012 The University of Melbourne.
|
|
% Copyright (C) 2013-2026 The Mercury team.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: mercury_compile_middle_passes.m.
|
|
%
|
|
% This module invokes the middle passes of the compiler as appropriate.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module top_level.mercury_compile_middle_passes.
|
|
:- interface.
|
|
|
|
:- import_module hlds.
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module hlds.passes_aux.
|
|
:- import_module libs.
|
|
:- import_module libs.op_mode.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.error_spec.
|
|
:- import_module parse_tree.prog_item.
|
|
|
|
:- import_module io.
|
|
:- import_module list.
|
|
:- import_module set.
|
|
|
|
:- pred middle_pass(io.text_output_stream::in, io.text_output_stream::in,
|
|
op_mode_front_and_middle::in,
|
|
module_info::in, module_info::out, dump_info::in, dump_info::out,
|
|
list(error_spec)::in, list(error_spec)::out, io::di, io::uo) is det.
|
|
|
|
:- pred middle_pass_for_opt_file(io.text_output_stream::in,
|
|
module_info::in, module_info::out, set(gen_pragma_unused_args_info)::out,
|
|
list(error_spec)::in, list(error_spec)::out, io::di, io::uo) is det.
|
|
|
|
:- pred output_trans_opt_file(io.text_output_stream::in, module_info::in,
|
|
list(error_spec)::in, list(error_spec)::out,
|
|
dump_info::in, dump_info::out, io::di, io::uo) is det.
|
|
|
|
:- pred output_analysis_file(io.text_output_stream::in, module_info::in,
|
|
list(error_spec)::in, list(error_spec)::out,
|
|
dump_info::in, dump_info::out, io::di, io::uo) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module analysis.
|
|
:- import_module analysis.operations.
|
|
:- import_module backend_libs.
|
|
:- import_module backend_libs.type_ctor_info.
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module hlds.mark_static_terms.
|
|
:- import_module libs.file_util.
|
|
:- import_module libs.globals.
|
|
:- import_module libs.optimization_options.
|
|
:- import_module libs.options.
|
|
:- import_module ll_backend.
|
|
:- import_module ll_backend.deep_profiling.
|
|
:- import_module parse_tree.file_names.
|
|
:- import_module parse_tree.module_cmds.
|
|
:- import_module parse_tree.parse_tree_out.
|
|
:- import_module parse_tree.parse_tree_out_info.
|
|
:- import_module parse_tree.write_error_spec.
|
|
:- import_module top_level.mercury_compile_front_end.
|
|
:- import_module transform_hlds.
|
|
:- import_module transform_hlds.accumulator.
|
|
:- import_module transform_hlds.closure_analysis.
|
|
:- import_module transform_hlds.complexity.
|
|
:- import_module transform_hlds.ctgc.
|
|
:- import_module transform_hlds.ctgc.selector.
|
|
:- import_module transform_hlds.ctgc.structure_reuse.
|
|
:- import_module transform_hlds.ctgc.structure_reuse.analysis.
|
|
:- import_module transform_hlds.ctgc.structure_sharing.
|
|
:- import_module transform_hlds.ctgc.structure_sharing.analysis.
|
|
:- import_module transform_hlds.dead_proc_elim.
|
|
:- import_module transform_hlds.deforest.
|
|
:- import_module transform_hlds.delay_construct.
|
|
:- import_module transform_hlds.dep_par_conj.
|
|
:- import_module transform_hlds.direct_arg_in_out.
|
|
:- import_module transform_hlds.distance_granularity.
|
|
:- import_module transform_hlds.equiv_type_hlds.
|
|
:- import_module transform_hlds.exception_analysis.
|
|
:- import_module transform_hlds.float_regs.
|
|
:- import_module transform_hlds.granularity.
|
|
:- import_module transform_hlds.higher_order.
|
|
:- import_module transform_hlds.higher_order.specialize_in_module.
|
|
:- import_module transform_hlds.implicit_parallelism.
|
|
:- import_module transform_hlds.implicit_parallelism.introduce_parallelism.
|
|
:- import_module transform_hlds.inlining.
|
|
:- import_module transform_hlds.intermod_analysis.
|
|
:- import_module transform_hlds.lambda.
|
|
:- import_module transform_hlds.lco.
|
|
:- import_module transform_hlds.loop_inv.
|
|
:- import_module transform_hlds.mmc_analysis.
|
|
:- import_module transform_hlds.par_loop_control.
|
|
:- import_module transform_hlds.parallel_to_plain_conj.
|
|
:- import_module transform_hlds.rbmm.
|
|
:- import_module transform_hlds.rbmm.region_analysis.
|
|
:- import_module transform_hlds.size_prof.
|
|
:- import_module transform_hlds.ssdebug.
|
|
:- import_module transform_hlds.stm_expand.
|
|
:- import_module transform_hlds.table_gen.
|
|
:- import_module transform_hlds.tabling_analysis.
|
|
:- import_module transform_hlds.term_constr_main.
|
|
:- import_module transform_hlds.termination.
|
|
:- import_module transform_hlds.trailing_analysis.
|
|
:- import_module transform_hlds.tupling.
|
|
:- import_module transform_hlds.unneeded_code.
|
|
:- import_module transform_hlds.untupling.
|
|
:- import_module transform_hlds.unused_args.
|
|
:- import_module transform_hlds.unused_args_warn_pragma.
|
|
|
|
:- import_module bool.
|
|
:- import_module int.
|
|
:- import_module map.
|
|
:- import_module maybe.
|
|
:- import_module pair.
|
|
:- import_module require.
|
|
:- import_module string.
|
|
:- import_module string.builder.
|
|
:- import_module univ.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
middle_pass(ProgressStream, ErrorStream, OpModeFrontAndMiddle,
|
|
!HLDS, !DumpInfo, !.Specs, Specs, !IO) :-
|
|
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, verbose, Verbose),
|
|
globals.lookup_bool_option(Globals, statistics, Stats),
|
|
|
|
maybe_read_experimental_complexity_file(ErrorStream, !HLDS, !IO),
|
|
|
|
tabling(ProgressStream, Verbose, Stats, !HLDS, !Specs, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 105, "tabling", !DumpInfo, !IO),
|
|
|
|
expand_lambdas(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 110, "lambda", !DumpInfo, !IO),
|
|
|
|
maybe_do_direct_arg_in_out_transform(ProgressStream, Verbose, Stats,
|
|
!HLDS, !Specs, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 111, "daio", !DumpInfo, !IO),
|
|
|
|
expand_stm_goals(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 113, "stm", !DumpInfo, !IO),
|
|
|
|
expand_equiv_types_hlds(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 115, "equiv_types",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_closure_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 117, "closure_analysis",
|
|
!DumpInfo, !IO),
|
|
|
|
% Uncomment the following code to check that unique mode analysis works
|
|
% after simplification has been run. Currently it does not because common.m
|
|
% does not preserve unique mode correctness (this test fails on about
|
|
% five modules in the compiler and library). It is important that unique
|
|
% mode analysis work most of the time after optimizations because
|
|
% deforestation reruns it.
|
|
|
|
% check_unique_modes(Verbose, Stats, !HLDS,
|
|
% FoundUniqError, !IO),
|
|
% ( if FoundUniqError = yes then
|
|
% error("unique modes failed")
|
|
% else
|
|
% true
|
|
% ),
|
|
|
|
% Exception analysis and termination analysis need to come before any
|
|
% optimization passes that could benefit from the information that
|
|
% they provide.
|
|
|
|
maybe_exception_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 118, "exception_analysis",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_termination(ProgressStream, Verbose, Stats, !HLDS, !Specs, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 120, "termination",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_termination2(ProgressStream, Verbose, Stats, !HLDS, !Specs, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 121, "termination2",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_type_ctor_infos(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 125, "type_ctor_infos",
|
|
!DumpInfo, !IO),
|
|
|
|
% warn_dead_procs must come after type_ctor_infos, so that it handles
|
|
% unification & comparison procedures correctly, but it must also come
|
|
% before optimizations such as higher-order specialization and inlining,
|
|
% which can make the original code for a procedure dead by
|
|
% inlining/specializing all uses of it.
|
|
maybe_warn_dead_procs(ProgressStream, Verbose, Stats, !.HLDS, !Specs, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 130, "warn_dead_procs",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_untuple_arguments(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 133, "untupling", !DumpInfo, !IO),
|
|
|
|
maybe_tuple_arguments(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 134, "tupling", !DumpInfo, !IO),
|
|
|
|
maybe_higher_order_or_type_spec(ProgressStream, Verbose, Stats,
|
|
!HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 135, "higher_order",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_source_to_source_debug(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 137, "ssdb", !DumpInfo, !IO),
|
|
|
|
maybe_introduce_accumulators(ProgressStream, Verbose, Stats,
|
|
!HLDS, !Specs, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 140, "accum", !DumpInfo, !IO),
|
|
|
|
maybe_do_inlining(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 145, "inlining", !DumpInfo, !IO),
|
|
|
|
% Hoisting loop invariants first invokes pass 148, "mark_static".
|
|
% "mark_static" is also run at stage 420.
|
|
maybe_loop_inv(ProgressStream, Verbose, Stats, !HLDS, !DumpInfo, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 150, "loop_inv", !DumpInfo, !IO),
|
|
|
|
maybe_deforestation(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 155, "deforestation",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_delay_construct(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 160, "delay_construct",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_structure_sharing_analysis(ProgressStream, Verbose, Stats,
|
|
!HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 162, "structure_sharing",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_structure_reuse_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 163, "structure_reuse",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_unused_args(ProgressStream, Verbose, Stats,
|
|
do_not_gather_pragma_unused_args, do_not_record_analysis_unused_args,
|
|
_PragmaUnusedArgsInfos, !HLDS, !Specs, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 165, "unused_args",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_analyse_trail_usage(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 167, "trail_usage",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_unneeded_code(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 170, "unneeded_code",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_simplify(ProgressStream, maybe.no, bool.no,
|
|
simplify_pass_pre_implicit_parallelism, Verbose, Stats,
|
|
!HLDS, [], _SimplifySpecsPreImpPar, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 172,
|
|
"pre_implicit_parallelism_simplify", !DumpInfo, !IO),
|
|
|
|
maybe_implicit_parallelism(ProgressStream, ErrorStream, Verbose, Stats,
|
|
!HLDS, !Specs, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 173, "implicit_parallelism",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_analyse_mm_tabling(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 185, "mm_tabling_analysis",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_control_granularity(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 200, "granularity",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_control_distance_granularity(ProgressStream, Verbose, Stats,
|
|
!HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 201, "distance_granularity",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_impl_dependent_par_conjs(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 205, "dependent_par_conj",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_par_loop_control(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 206, "par_loop_control",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_lco(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 210, "lco", !DumpInfo, !IO),
|
|
|
|
maybe_float_reg_wrapper(ProgressStream, Verbose, Stats,
|
|
!HLDS, !Specs, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 213, "float_reg_wrapper",
|
|
!DumpInfo, !IO),
|
|
|
|
% With OpModeFrontAndMiddle = opfam_errorcheck_only, it may make sense
|
|
% to execute only those passes in the middle end that can report errors.
|
|
% However, some passes that cannot return new error_specs may nevertheless
|
|
% be needed. They may be needed
|
|
%
|
|
% - because they establish invariants that later middle end passes
|
|
% depend on, or
|
|
%
|
|
% - because the changes they make to the HLDS affect the diagnostics
|
|
% that later passes would generate.
|
|
%
|
|
% The pass that expands out all lambda goals is an example of the former,
|
|
% while the pass that expands out HLDS equivalence types is an example
|
|
% of the latter.
|
|
%
|
|
% What we can do is stop after the last middle end pass that can generate
|
|
% diagnostics, so that is what we do.
|
|
Specs = !.Specs,
|
|
(
|
|
OpModeFrontAndMiddle = opfam_errorcheck_only
|
|
;
|
|
( OpModeFrontAndMiddle = opfam_target_code_only
|
|
; OpModeFrontAndMiddle = opfam_target_and_object_code_only
|
|
; OpModeFrontAndMiddle = opfam_target_object_and_executable
|
|
),
|
|
|
|
% If we are compiling in a deep profiling grade, then now rerun
|
|
% simplify. The reason for doing this now is that we want to
|
|
% take advantage of any opportunities the other optimizations
|
|
% have provided for constant propagation, and we cannot do that
|
|
% once the term-size profiling or deep profiling transformations
|
|
% have been applied.
|
|
maybe_simplify(ProgressStream, maybe.no, bool.no,
|
|
simplify_pass_pre_prof_transforms, Verbose, Stats, !HLDS,
|
|
[], _SimplifySpecsPreProf, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 215,
|
|
"pre_prof_transforms_simplify", !DumpInfo, !IO),
|
|
|
|
% The term size profiling transformation should be after all
|
|
% transformations that construct terms of non-zero size.
|
|
% (Deep profiling does not construct non-zero size terms.)
|
|
maybe_term_size_prof(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 220, "term_size_prof",
|
|
!DumpInfo, !IO),
|
|
|
|
% The deep profiling transformation should be done late in the piece
|
|
% since it munges the code a fair amount and introduces strange
|
|
% disjunctions that might confuse other hlds->hlds transformations.
|
|
maybe_deep_profiling(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 225, "deep_profiling",
|
|
!DumpInfo, !IO),
|
|
|
|
% Experimental complexity transformation should be done late in the
|
|
% piece for the same reason as deep profiling. At the moment, they are
|
|
% exclusive.
|
|
maybe_experimental_complexity(ProgressStream, Verbose, Stats,
|
|
!HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 230, "complexity",
|
|
!DumpInfo, !IO),
|
|
|
|
% XXX This may be moved to later.
|
|
maybe_region_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 240, "region_analysis",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_eliminate_dead_procs(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 250, "dead_procs",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 299, "middle_pass",
|
|
!DumpInfo, !IO)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
middle_pass_for_opt_file(ProgressStream, !HLDS, PragmaUnusedArgsInfos,
|
|
!Specs, !IO) :-
|
|
% NOTE If you add any passes here, you will probably need to change the
|
|
% code in mercury_compile_front_end.m that decides whether to call
|
|
% this predicate.
|
|
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, verbose, Verbose),
|
|
globals.lookup_bool_option(Globals, statistics, Stats),
|
|
globals.lookup_bool_option(Globals, analyse_closures, ClosureAnalysis),
|
|
globals.lookup_bool_option(Globals, structure_sharing_analysis,
|
|
SharingAnalysis),
|
|
( if
|
|
% Closure analysis assumes that lambda expressions have been converted
|
|
% into separate predicates.
|
|
% Structure sharing/reuse analysis results can be affected
|
|
% by expand_lambdas.
|
|
( ClosureAnalysis = yes
|
|
; SharingAnalysis = yes
|
|
)
|
|
then
|
|
expand_lambdas(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
expand_stm_goals(ProgressStream, Verbose, Stats, !HLDS, !IO)
|
|
else
|
|
true
|
|
),
|
|
maybe_closure_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_exception_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_unused_args(ProgressStream, Verbose, Stats,
|
|
do_gather_pragma_unused_args, do_not_record_analysis_unused_args,
|
|
PragmaUnusedArgsInfos, !HLDS, !Specs, !IO),
|
|
maybe_termination(ProgressStream, Verbose, Stats, !HLDS, !Specs, !IO),
|
|
maybe_termination2(ProgressStream, Verbose, Stats, !HLDS, !Specs, !IO),
|
|
maybe_structure_sharing_analysis(ProgressStream, Verbose, Stats,
|
|
!HLDS, !IO),
|
|
maybe_structure_reuse_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_analyse_trail_usage(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_analyse_mm_tabling(ProgressStream, Verbose, Stats, !HLDS, !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
output_trans_opt_file(ProgressStream, !.HLDS, !Specs, !DumpInfo, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, verbose, Verbose),
|
|
globals.lookup_bool_option(Globals, statistics, Stats),
|
|
globals.lookup_bool_option(Globals, analyse_closures, ClosureAnalysis),
|
|
globals.lookup_bool_option(Globals, structure_sharing_analysis,
|
|
SharingAnalysis),
|
|
|
|
% Closure analysis assumes that lambda expressions have
|
|
% been converted into separate predicates.
|
|
( if
|
|
( ClosureAnalysis = yes
|
|
; SharingAnalysis = yes
|
|
)
|
|
then
|
|
expand_lambdas(ProgressStream, Verbose, Stats, !HLDS, !IO)
|
|
else
|
|
true
|
|
),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 110, "lambda", !DumpInfo, !IO),
|
|
maybe_closure_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 117, "closure_analysis",
|
|
!DumpInfo, !IO),
|
|
maybe_exception_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 118, "exception_analysis",
|
|
!DumpInfo, !IO),
|
|
maybe_termination(ProgressStream, Verbose, Stats, !HLDS, !Specs, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 120, "termination",
|
|
!DumpInfo, !IO),
|
|
maybe_termination2(ProgressStream, Verbose, Stats, !HLDS, !Specs, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 121, "termination_2",
|
|
!DumpInfo, !IO),
|
|
(
|
|
SharingAnalysis = yes,
|
|
% These affect the results we write out for structure sharing/reuse
|
|
% analysis.
|
|
maybe_higher_order_or_type_spec(ProgressStream, Verbose, Stats,
|
|
!HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 135, "higher_order",
|
|
!DumpInfo, !IO),
|
|
maybe_do_inlining(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 145, "inlining",
|
|
!DumpInfo, !IO),
|
|
maybe_loop_inv(ProgressStream, Verbose, Stats, !HLDS, !DumpInfo, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 150, "loop_inv",
|
|
!DumpInfo, !IO),
|
|
maybe_deforestation(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 155, "deforestation",
|
|
!DumpInfo, !IO)
|
|
;
|
|
SharingAnalysis = no
|
|
),
|
|
maybe_structure_sharing_analysis(ProgressStream, Verbose, Stats,
|
|
!HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 162, "structure_sharing",
|
|
!DumpInfo, !IO),
|
|
maybe_structure_reuse_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 163, "structure_reuse",
|
|
!DumpInfo, !IO),
|
|
maybe_analyse_trail_usage(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 167, "trail_usage",
|
|
!DumpInfo, !IO),
|
|
maybe_analyse_mm_tabling(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 185, "mm_tabling_analysis",
|
|
!DumpInfo, !IO),
|
|
|
|
TransOptState0 = string.builder.init,
|
|
format_trans_opt_file(!.HLDS, ParseTreeTransOpt,
|
|
TransOptState0, TransOptState),
|
|
TransOptFileStr = string.builder.to_string(TransOptState),
|
|
|
|
module_info_get_name(!.HLDS, ModuleName),
|
|
% XXX LEGACY
|
|
TransOptExt =
|
|
ext_cur_ngs_gs_max_ngs(ext_cur_ngs_gs_max_ngs_legacy_opt_trans),
|
|
module_name_to_file_name_create_dirs(Globals, $pred, TransOptExt,
|
|
ModuleName, TransOptFileName, _TransOptFileNameProposed, !IO),
|
|
|
|
io.read_named_file_as_string(TransOptFileName, ReadFileResult, !IO),
|
|
(
|
|
ReadFileResult = ok(OldTransOptFileStr),
|
|
( if OldTransOptFileStr = TransOptFileStr then
|
|
WriteTransOpt = bool.no
|
|
else
|
|
WriteTransOpt = bool.yes
|
|
)
|
|
;
|
|
ReadFileResult = error(_),
|
|
% It does not matter why we cannot read the old version of the file,
|
|
% we should try to write out the new version.
|
|
WriteTransOpt = bool.yes
|
|
),
|
|
|
|
(
|
|
WriteTransOpt = no,
|
|
TouchDateFile = yes
|
|
;
|
|
WriteTransOpt = yes,
|
|
io.open_output(TransOptFileName, WriteFileResult, !IO),
|
|
(
|
|
WriteFileResult = ok(TransOptStream),
|
|
io.write_string(TransOptStream, TransOptFileStr, !IO),
|
|
io.close_output(TransOptStream, !IO),
|
|
TouchDateFile = yes,
|
|
|
|
globals.lookup_bool_option(Globals, experiment5, Experiment5),
|
|
(
|
|
Experiment5 = no
|
|
;
|
|
Experiment5 = yes,
|
|
io.open_output(TransOptFileName ++ "x", TransOptXResult, !IO),
|
|
(
|
|
TransOptXResult = error(_)
|
|
;
|
|
TransOptXResult = ok(TransOptXStream),
|
|
Info = init_merc_out_info(Globals, unqualified_item_names,
|
|
output_mercury),
|
|
TransOptXState0 = string.builder.init,
|
|
mercury_format_parse_tree_trans_opt(Info,
|
|
string.builder.handle, ParseTreeTransOpt,
|
|
TransOptXState0, TransOptXState),
|
|
TransOptXFileStr =
|
|
string.builder.to_string(TransOptXState),
|
|
io.write_string(TransOptXStream, TransOptXFileStr, !IO),
|
|
io.close_output(TransOptXStream, !IO)
|
|
)
|
|
)
|
|
;
|
|
WriteFileResult = error(Error),
|
|
TouchDateFile = no,
|
|
io.progname_base("mmc", ProgName, !IO),
|
|
io.error_message(Error, ErrorMsg),
|
|
io.format(ProgressStream,
|
|
"%s: cannot open `%s' for output: %s\n",
|
|
[s(ProgName), s(TransOptFileName), s(ErrorMsg)], !IO),
|
|
io.set_exit_status(1, !IO)
|
|
)
|
|
),
|
|
|
|
(
|
|
TouchDateFile = no
|
|
;
|
|
TouchDateFile = yes,
|
|
% We update the .trans_opt_date file's timestamp whether or not
|
|
% we wrote out a new version of the .trans_opt file.
|
|
TransOptDateExt = ext_cur_ngs_gs(ext_cur_ngs_gs_opt_date_trans),
|
|
touch_module_ext_datestamp(Globals, ProgressStream,
|
|
ModuleName, TransOptDateExt, _TouchSucceeded, !IO)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
output_analysis_file(ProgressStream, !.HLDS, !Specs, !DumpInfo, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, verbose, Verbose),
|
|
globals.lookup_bool_option(Globals, statistics, Stats),
|
|
globals.lookup_bool_option(Globals, analyse_closures, ClosureAnalysis),
|
|
globals.lookup_bool_option(Globals, structure_sharing_analysis,
|
|
SharingAnalysis),
|
|
|
|
% Closure analysis assumes that lambda expressions have
|
|
% been converted into separate predicates.
|
|
( if
|
|
( ClosureAnalysis = yes
|
|
; SharingAnalysis = yes
|
|
)
|
|
then
|
|
expand_lambdas(ProgressStream, Verbose, Stats, !HLDS, !IO)
|
|
else
|
|
true
|
|
),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 110, "lambda", !DumpInfo, !IO),
|
|
maybe_closure_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 117, "closure_analysis",
|
|
!DumpInfo, !IO),
|
|
maybe_exception_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 118, "exception_analysis",
|
|
!DumpInfo, !IO),
|
|
maybe_termination(ProgressStream, Verbose, Stats, !HLDS, !Specs, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 120, "termination",
|
|
!DumpInfo, !IO),
|
|
maybe_termination2(ProgressStream, Verbose, Stats, !HLDS, !Specs, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 121, "termination_2",
|
|
!DumpInfo, !IO),
|
|
(
|
|
SharingAnalysis = yes,
|
|
% These affect the results we write out for structure sharing/reuse
|
|
% analysis.
|
|
maybe_higher_order_or_type_spec(ProgressStream, Verbose, Stats,
|
|
!HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 135, "higher_order",
|
|
!DumpInfo, !IO),
|
|
maybe_do_inlining(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 145, "inlining",
|
|
!DumpInfo, !IO),
|
|
maybe_loop_inv(ProgressStream, Verbose, Stats, !HLDS, !DumpInfo, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 150, "loop_inv",
|
|
!DumpInfo, !IO),
|
|
maybe_deforestation(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 155, "deforestation",
|
|
!DumpInfo, !IO)
|
|
;
|
|
SharingAnalysis = no
|
|
),
|
|
maybe_structure_sharing_analysis(ProgressStream, Verbose, Stats,
|
|
!HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 162, "structure_sharing",
|
|
!DumpInfo, !IO),
|
|
maybe_structure_reuse_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 163, "structure_reuse",
|
|
!DumpInfo, !IO),
|
|
maybe_unused_args(ProgressStream, Verbose, Stats,
|
|
do_not_gather_pragma_unused_args, do_record_analysis_unused_args,
|
|
_PragmaUnusedArgsInfos, !HLDS, !Specs, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 165, "unused_args",
|
|
!DumpInfo, !IO),
|
|
maybe_analyse_trail_usage(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 167, "trail_usage",
|
|
!DumpInfo, !IO),
|
|
maybe_analyse_mm_tabling(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 185, "mm_tabling_analysis",
|
|
!DumpInfo, !IO),
|
|
|
|
module_info_get_analysis_info(!.HLDS, AnalysisInfo),
|
|
module_info_get_all_avail_modules(!.HLDS, AllAvailModules),
|
|
% XXX Is AllAvailModules the right set of modules to pass here?
|
|
analysis.operations.write_analysis_files(ProgressStream, mmc, !.HLDS,
|
|
AllAvailModules, AnalysisInfo, AnalysisSpecs, !IO),
|
|
!:Specs = AnalysisSpecs ++ !.Specs.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% The various component passes of the middle pass.
|
|
% Please keep these predicates in the order of their (first) invocation.
|
|
%
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_read_experimental_complexity_file(io.text_output_stream::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_read_experimental_complexity_file(ErrorStream, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_string_option(Globals, experimental_complexity, FileName),
|
|
( if FileName = "" then
|
|
% While we could include the following sanity check, it is overly
|
|
% strong. For example, a bootcheck in a term size profiling grade
|
|
% would have to supply an --experimental-complexity option for
|
|
% both the stage3 compiler and the test cases. Since the runtime
|
|
% checks that all procedures mentioned in the files actually
|
|
% exist and are transformed by the compiler, this would require
|
|
% a different complexity experiment file for each test case,
|
|
% which is impractical.
|
|
% (
|
|
% RecordTermSizes = yes,
|
|
% report_error("term size profiling grades require " ++
|
|
% "the --experimental-complexity option", !IO)
|
|
% ;
|
|
% RecordTermSizes = no
|
|
% )
|
|
true
|
|
else
|
|
complexity.read_spec_file(FileName, MaybeNumProcMap, !IO),
|
|
(
|
|
MaybeNumProcMap = ok(NumProcs - ProcMap),
|
|
module_info_set_maybe_complexity_proc_map(yes(NumProcs - ProcMap),
|
|
!HLDS)
|
|
;
|
|
MaybeNumProcMap = error(Msg),
|
|
report_arbitrary_error(ErrorStream, Msg, !IO)
|
|
)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred tabling(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out,
|
|
list(error_spec)::in, list(error_spec)::out, io::di, io::uo) is det.
|
|
|
|
tabling(ProgressStream, Verbose, Stats, !HLDS, !Specs, !IO) :-
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Transforming tabled predicates...", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
table_gen_process_module(!HLDS, !Specs),
|
|
maybe_write_string(ProgressStream, Verbose, " done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred expand_lambdas(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
expand_lambdas(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Transforming lambda expressions...", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
expand_lambdas_in_module(!HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, " done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_do_direct_arg_in_out_transform(io.text_output_stream::in,
|
|
bool::in, bool::in, module_info::in, module_info::out,
|
|
list(error_spec)::in, list(error_spec)::out, io::di, io::uo) is det.
|
|
|
|
maybe_do_direct_arg_in_out_transform(ProgressStream, Verbose, Stats,
|
|
!HLDS, !Specs, !IO) :-
|
|
module_info_get_direct_arg_proc_map(!.HLDS, DirectArgProcMap),
|
|
( if map.is_empty(DirectArgProcMap) then
|
|
true
|
|
else
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Transforming direct arg in out procedures...\n", !IO),
|
|
do_direct_arg_in_out_transform_in_module(ProgressStream,
|
|
DirectArgProcMap, !HLDS, DirectArgSpecs),
|
|
!:Specs = DirectArgSpecs ++ !.Specs,
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred expand_stm_goals(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
expand_stm_goals(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Transforming stm expressions...", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
stm_process_module(!HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, " done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred expand_equiv_types_hlds(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
expand_equiv_types_hlds(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Fully expanding equivalence types...", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
replace_equiv_types_in_hlds(!HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, " done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_closure_analysis(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_closure_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, analyse_closures, ClosureAnalysis),
|
|
(
|
|
ClosureAnalysis = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Analysing closures...\n", !IO),
|
|
closure_analyse_module(ProgressStream, !HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
ClosureAnalysis = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_exception_analysis(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_exception_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, analyse_exceptions, ExceptionAnalysis),
|
|
(
|
|
ExceptionAnalysis = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Analysing exceptions...\n", !IO),
|
|
analyse_exceptions_in_module(!HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
ExceptionAnalysis = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_termination(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out,
|
|
list(error_spec)::in, list(error_spec)::out, io::di, io::uo) is det.
|
|
|
|
maybe_termination(ProgressStream, Verbose, Stats, !HLDS, !Specs, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, termination_enable, Termination),
|
|
(
|
|
Termination = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Detecting termination...\n", !IO),
|
|
analyse_termination_in_module(!HLDS, TermSpecs),
|
|
!:Specs = TermSpecs ++ !.Specs,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Termination checking done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
Termination = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_termination2(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out,
|
|
list(error_spec)::in, list(error_spec)::out, io::di, io::uo) is det.
|
|
|
|
maybe_termination2(ProgressStream, Verbose, Stats, !HLDS, !Specs, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, termination2_enable, Termination2),
|
|
(
|
|
Termination2 = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Detecting termination 2...\n", !IO),
|
|
term2_analyse_module(!HLDS, TermSpecs),
|
|
!:Specs = TermSpecs ++ !.Specs,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Termination 2 checking done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
Termination2 = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_type_ctor_infos(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_type_ctor_infos(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, type_ctor_info, TypeCtorInfo),
|
|
(
|
|
TypeCtorInfo = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Generating type_ctor_info structures...", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
type_ctor_info.generate_hlds(!HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, " done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
TypeCtorInfo = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_warn_dead_procs(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, list(error_spec)::in, list(error_spec)::out,
|
|
io::di, io::uo) is det.
|
|
|
|
maybe_warn_dead_procs(ProgressStream, Verbose, Stats, HLDS, !Specs, !IO) :-
|
|
module_info_get_globals(HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, warn_dead_procs, WarnDeadProcs),
|
|
globals.lookup_bool_option(Globals, warn_dead_preds, WarnDeadPreds),
|
|
( if
|
|
( WarnDeadProcs = yes
|
|
; WarnDeadPreds = yes
|
|
)
|
|
then
|
|
(
|
|
WarnDeadProcs = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Warning about dead procedures...\n", !IO)
|
|
;
|
|
WarnDeadProcs = no,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Warning about dead predicates...\n", !IO)
|
|
),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
dead_proc_warn(HLDS, DeadSpecs),
|
|
!:Specs = DeadSpecs ++ !.Specs,
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
else
|
|
true
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_untuple_arguments(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_untuple_arguments(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
Untuple = OptTuple ^ ot_untuple,
|
|
(
|
|
Untuple = untuple,
|
|
maybe_write_string(ProgressStream, Verbose, "% Untupling...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
untuple_arguments(!HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_simplify(ProgressStream, maybe.no, bool.no,
|
|
simplify_pass_post_untuple, Verbose, Stats, !HLDS,
|
|
[], _SimplifySpecs, !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
Untuple = do_not_untuple
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_tuple_arguments(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_tuple_arguments(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
Tuple = OptTuple ^ ot_tuple,
|
|
(
|
|
Tuple = tuple,
|
|
maybe_write_string(ProgressStream, Verbose, "% Tupling...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
tuple_arguments(ProgressStream, !HLDS, !IO),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
Tuple = do_not_tuple
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_higher_order_or_type_spec(io.text_output_stream::in,
|
|
bool::in, bool::in, module_info::in, module_info::out,
|
|
io::di, io::uo) is det.
|
|
|
|
maybe_higher_order_or_type_spec(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
HigherOrder = OptTuple ^ ot_opt_higher_order,
|
|
% --type-specialization implies --user-guided-type-specialization.
|
|
UserTypeSpec = OptTuple ^ ot_spec_types_user_guided,
|
|
|
|
% Always produce the specialized versions for which
|
|
% `:- pragma type_spec' declarations exist, because
|
|
% importing modules might call them.
|
|
module_info_get_type_spec_tables(!.HLDS, TypeSpecTables),
|
|
TypeSpecTables = type_spec_tables(TypeSpecPreds, _, _, _),
|
|
( if
|
|
( HigherOrder = opt_higher_order
|
|
; UserTypeSpec = spec_types_user_guided
|
|
; set.is_non_empty(TypeSpecPreds)
|
|
)
|
|
then
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Specializing higher-order and polymorphic predicates...\n",
|
|
!IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
|
|
specialize_higher_order(ProgressStream, !HLDS, !IO),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
else
|
|
true
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_source_to_source_debug(io.text_output_stream::in,
|
|
bool::in, bool::in, module_info::in, module_info::out,
|
|
io::di, io::uo) is det.
|
|
|
|
maybe_source_to_source_debug(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, force_disable_ssdebug,
|
|
ForceDisableSSDB),
|
|
(
|
|
ForceDisableSSDB = no,
|
|
globals.get_ssdb_trace_level(Globals, SSTraceLevel),
|
|
(
|
|
SSTraceLevel = ssdb_none
|
|
;
|
|
( SSTraceLevel = ssdb_shallow
|
|
; SSTraceLevel = ssdb_deep
|
|
),
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Apply source to source debugging transformation ...\n",
|
|
!IO),
|
|
ssdebug_transform_module(SSTraceLevel, !HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
)
|
|
;
|
|
ForceDisableSSDB = yes
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_implicit_parallelism(io.text_output_stream::in,
|
|
io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out,
|
|
list(error_spec)::in, list(error_spec)::out, io::di, io::uo) is det.
|
|
|
|
maybe_implicit_parallelism(ProgressStream, ErrorStream, Verbose, Stats,
|
|
!HLDS, !Specs, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, implicit_parallelism,
|
|
ImplicitParallelism),
|
|
(
|
|
ImplicitParallelism = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Applying implicit parallelism...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
apply_implicit_parallelism_transformation(ParSpecs, !HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
% XXX This is a bit late for printing errors.
|
|
!:Specs = ParSpecs ++ !.Specs,
|
|
maybe_write_out_errors(ErrorStream, Verbose, Globals, !Specs, !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
% The user hasn't asked for implicit parallelism.
|
|
ImplicitParallelism = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_introduce_accumulators(io.text_output_stream::in,
|
|
bool::in, bool::in, module_info::in, module_info::out,
|
|
list(error_spec)::in, list(error_spec)::out, io::di, io::uo) is det.
|
|
|
|
maybe_introduce_accumulators(ProgressStream, Verbose, Stats,
|
|
!HLDS, !Specs, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
IntroduceAccumulators = OptTuple ^ ot_introduce_accumulators,
|
|
(
|
|
IntroduceAccumulators = introduce_accumulators,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Attempting to introduce accumulators...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
type_to_univ([] : list(error_spec), Cookie0),
|
|
Task0 = update_module_pred_cookie(
|
|
accu_transform_proc(ProgressStream), Cookie0),
|
|
process_valid_nonimported_procs_update(Task0, Task, !HLDS),
|
|
( if
|
|
Task = update_module_pred_cookie(_, Cookie),
|
|
univ_to_type(Cookie, AccSpecs)
|
|
then
|
|
!:Specs = AccSpecs ++ !.Specs
|
|
else
|
|
unexpected($pred, "bad task")
|
|
),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
IntroduceAccumulators = do_not_introduce_accumulators
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_do_inlining(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_do_inlining(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
Allow = OptTuple ^ ot_allow_inlining,
|
|
Simple = OptTuple ^ ot_inline_simple,
|
|
SingleUse = OptTuple ^ ot_inline_single_use,
|
|
Threshold = OptTuple ^ ot_inline_compound_threshold,
|
|
( if
|
|
Allow = allow_inlining,
|
|
( Simple = inline_simple
|
|
; SingleUse = inline_single_use
|
|
; Threshold > 0
|
|
)
|
|
then
|
|
maybe_write_string(ProgressStream, Verbose, "% Inlining...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
inline_in_module(ProgressStream, !HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
else
|
|
true
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_loop_inv(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, dump_info::in, dump_info::out,
|
|
io::di, io::uo) is det.
|
|
|
|
maybe_loop_inv(ProgressStream, Verbose, Stats, !HLDS, !DumpInfo, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
LoopInv = OptTuple ^ ot_opt_loop_invariants,
|
|
(
|
|
LoopInv = opt_loop_invariants,
|
|
% We run the mark_static pass because we need the construct_how flag
|
|
% to be valid.
|
|
maybe_mark_static_terms(ProgressStream, Verbose, Stats, !HLDS, !IO),
|
|
maybe_dump_hlds(ProgressStream, !.HLDS, 148, "mark_static",
|
|
!DumpInfo, !IO),
|
|
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Hoisting loop invariants...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
process_valid_nonimported_procs(
|
|
update_module_pred(hoist_loop_invariants), !HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
LoopInv = do_not_opt_loop_invariants
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_deforestation(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_deforestation(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
Deforest = OptTuple ^ ot_deforest,
|
|
|
|
% --constraint-propagation implies --local-constraint-propagation.
|
|
PropLocalConstraints = OptTuple ^ ot_prop_local_constraints,
|
|
(
|
|
Deforest = do_not_deforest,
|
|
PropLocalConstraints = do_not_prop_local_constraints
|
|
;
|
|
(
|
|
Deforest = deforest,
|
|
PropLocalConstraints = prop_local_constraints,
|
|
Msg = "% Deforestation and constraint propagation...\n"
|
|
;
|
|
Deforest = deforest,
|
|
PropLocalConstraints = do_not_prop_local_constraints,
|
|
Msg = "% Deforestation...\n"
|
|
;
|
|
Deforest = do_not_deforest,
|
|
PropLocalConstraints = prop_local_constraints,
|
|
Msg = "% Constraint propagation...\n"
|
|
),
|
|
maybe_write_string(ProgressStream, Verbose, Msg, !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
deforest_module(ProgressStream, !HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_delay_construct(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_delay_construct(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
DelayConstruct = OptTuple ^ ot_delay_constructs,
|
|
(
|
|
DelayConstruct = delay_constructs,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Delaying construction unifications ...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
process_valid_nonimported_procs(
|
|
update_proc_ids(delay_construct_proc(ProgressStream)), !HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
DelayConstruct = do_not_delay_constructs
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_structure_sharing_analysis(io.text_output_stream::in,
|
|
bool::in, bool::in, module_info::in, module_info::out,
|
|
io::di, io::uo) is det.
|
|
|
|
maybe_structure_sharing_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, structure_sharing_analysis, Sharing),
|
|
(
|
|
Sharing = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Structure sharing analysis...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
perform_structure_sharing_analysis(ProgressStream, !HLDS),
|
|
transform_hlds.ctgc.selector.reset_tables(!IO),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
Sharing = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_structure_reuse_analysis(io.text_output_stream::in,
|
|
bool::in, bool::in, module_info::in, module_info::out,
|
|
io::di, io::uo) is det.
|
|
|
|
maybe_structure_reuse_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, structure_reuse_analysis,
|
|
ReuseAnalysis),
|
|
(
|
|
ReuseAnalysis = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Structure reuse analysis...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
perform_structure_reuse_analysis(ProgressStream, !HLDS),
|
|
transform_hlds.ctgc.selector.reset_tables(!IO),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
ReuseAnalysis = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_unused_args(io.text_output_stream::in, bool::in, bool::in,
|
|
maybe_gather_pragma_unused_args::in, maybe_record_analysis_unused_args::in,
|
|
set(gen_pragma_unused_args_info)::out, module_info::in, module_info::out,
|
|
list(error_spec)::in, list(error_spec)::out, io::di, io::uo) is det.
|
|
|
|
maybe_unused_args(ProgressStream, Verbose, Stats,
|
|
GatherPragmas, RecordAnalysis, PragmaUnusedArgsInfos,
|
|
!HLDS, !Specs, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
OptUnusedArgs = OptTuple ^ ot_opt_unused_args,
|
|
OptUnusedArgsIntermod = OptTuple ^ ot_opt_unused_args_intermod,
|
|
globals.lookup_bool_option(Globals, warn_unused_args, WarnUnusedArgs),
|
|
( if
|
|
( OptUnusedArgs = opt_unused_args
|
|
; OptUnusedArgsIntermod = opt_unused_args_intermod
|
|
; WarnUnusedArgs = yes
|
|
)
|
|
then
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Finding unused arguments ...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
unused_args_process_module(GatherPragmas, RecordAnalysis,
|
|
UnusedSpecs, PragmaUnusedArgsInfos, !HLDS),
|
|
!:Specs = UnusedSpecs ++ !.Specs,
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
else
|
|
set.init(PragmaUnusedArgsInfos)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_analyse_trail_usage(io.text_output_stream::in,
|
|
bool::in, bool::in, module_info::in, module_info::out,
|
|
io::di, io::uo) is det.
|
|
|
|
maybe_analyse_trail_usage(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, analyse_trail_usage, AnalyseTrail),
|
|
(
|
|
AnalyseTrail = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Analysing trail usage...\n", !IO),
|
|
analyse_trail_usage_in_module(!HLDS),
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Trail usage analysis done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
AnalyseTrail = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_unneeded_code(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_unneeded_code(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
UnneededCode = OptTuple ^ ot_opt_unneeded_code,
|
|
(
|
|
UnneededCode = opt_unneeded_code,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Removing unneeded code from procedure bodies...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
process_valid_nonimported_procs(
|
|
update_module(unneeded_process_proc_msg(ProgressStream)), !HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
UnneededCode = do_not_opt_unneeded_code
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_lco(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_lco(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
LCMC = OptTuple ^ ot_opt_lcmc,
|
|
(
|
|
LCMC = opt_lcmc,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Looking for LCO modulo constructor application ...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
lco_modulo_constructors(!HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
LCMC = do_not_opt_lcmc
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_analyse_mm_tabling(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_analyse_mm_tabling(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, analyse_mm_tabling, TablingAnalysis),
|
|
(
|
|
TablingAnalysis = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Analysing minimal model tabling...\n", !IO),
|
|
analyse_mm_tabling_in_module(!HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
TablingAnalysis = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_control_granularity(io.text_output_stream::in,
|
|
bool::in, bool::in, module_info::in, module_info::out,
|
|
io::di, io::uo) is det.
|
|
|
|
maybe_control_granularity(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, parallel, Parallel),
|
|
globals.lookup_bool_option(Globals, highlevel_code, HighLevelCode),
|
|
globals.lookup_bool_option(Globals, control_granularity, Control),
|
|
module_info_get_has_parallel_conj(!.HLDS, HasParallelConj),
|
|
( if
|
|
% If either of these is false, there is no parallelism to control.
|
|
Parallel = yes,
|
|
HasParallelConj = has_parallel_conj,
|
|
|
|
% Our mechanism for granularity control only works for the low level
|
|
% backend.
|
|
HighLevelCode = no,
|
|
|
|
% If this is false, then the user hasn't asked for granularity control.
|
|
Control = yes
|
|
then
|
|
globals.get_target(Globals, Target),
|
|
(
|
|
Target = target_c,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Granularity control transformation...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
control_granularity(!HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
( Target = target_csharp
|
|
; Target = target_java
|
|
)
|
|
% Leave the HLDS alone. We cannot implement parallelism,
|
|
% so there is not point in controlling its granularity.
|
|
)
|
|
else
|
|
true
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_control_distance_granularity(io.text_output_stream::in,
|
|
bool::in, bool::in, module_info::in, module_info::out,
|
|
io::di, io::uo) is det.
|
|
|
|
maybe_control_distance_granularity(ProgressStream, Verbose, Stats,
|
|
!HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, parallel, Parallel),
|
|
globals.lookup_bool_option(Globals, highlevel_code, HighLevelCode),
|
|
globals.lookup_int_option(Globals, distance_granularity, Distance),
|
|
module_info_get_has_parallel_conj(!.HLDS, HasParallelConj),
|
|
( if
|
|
% If either of these is false, there is no parallelism to control.
|
|
Parallel = yes,
|
|
HasParallelConj = has_parallel_conj,
|
|
|
|
% Our mechanism for granularity control only works for the low level
|
|
% backend.
|
|
HighLevelCode = no,
|
|
|
|
% Distance must be greater than 0 to apply the distance granularity
|
|
% transformation.
|
|
Distance > 0
|
|
then
|
|
globals.get_target(Globals, Target),
|
|
(
|
|
Target = target_c,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Distance granularity transformation...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
control_distance_granularity(!HLDS, Distance),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
( Target = target_csharp
|
|
; Target = target_java
|
|
)
|
|
% Leave the HLDS alone. We cannot implement parallelism,
|
|
% so there is not point in controlling its granularity.
|
|
)
|
|
else
|
|
true
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_impl_dependent_par_conjs(io.text_output_stream::in,
|
|
bool::in, bool::in, module_info::in, module_info::out,
|
|
io::di, io::uo) is det.
|
|
|
|
maybe_impl_dependent_par_conjs(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_has_parallel_conj(!.HLDS, HasParallelConj),
|
|
(
|
|
HasParallelConj = has_parallel_conj,
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
current_grade_supports_par_conj(Globals, SupportsParConj),
|
|
(
|
|
SupportsParConj = no,
|
|
process_valid_nonimported_procs(
|
|
update_proc_ids(parallel_to_plain_conjs), !HLDS)
|
|
;
|
|
SupportsParConj = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Dependent parallel conjunction transformation...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
impl_dep_par_conjs_in_module(ProgressStream, !HLDS),
|
|
dead_proc_elim(do_not_elim_opt_imported, _, _, !HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
)
|
|
;
|
|
HasParallelConj = has_no_parallel_conj
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_par_loop_control(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_par_loop_control(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, par_loop_control, LoopControl),
|
|
(
|
|
LoopControl = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Applying parallel loop control transformation...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
maybe_par_loop_control_module(!HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
LoopControl = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_float_reg_wrapper(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out,
|
|
list(error_spec)::in, list(error_spec)::out, io::di, io::uo) is det.
|
|
|
|
maybe_float_reg_wrapper(ProgressStream, Verbose, Stats, !HLDS, !Specs, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, use_float_registers, UseFloatRegs),
|
|
(
|
|
UseFloatRegs = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Inserting float register wrappers...", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
float_regs.insert_reg_wrappers(!HLDS, RegSpecs),
|
|
!:Specs = RegSpecs ++ !.Specs,
|
|
maybe_write_string(ProgressStream, Verbose, " done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
UseFloatRegs = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_term_size_prof(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_term_size_prof(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, record_term_sizes_as_words, AsWords),
|
|
globals.lookup_bool_option(Globals, record_term_sizes_as_cells, AsCells),
|
|
(
|
|
AsWords = yes,
|
|
AsCells = yes,
|
|
unexpected($pred, "as_words and as_cells")
|
|
;
|
|
AsWords = yes,
|
|
AsCells = no,
|
|
MaybeTransform = yes(term_words)
|
|
;
|
|
AsWords = no,
|
|
AsCells = yes,
|
|
MaybeTransform = yes(term_cells)
|
|
;
|
|
AsWords = no,
|
|
AsCells = no,
|
|
MaybeTransform = no
|
|
),
|
|
(
|
|
MaybeTransform = yes(Transform),
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Applying term size profiling transformation...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
process_valid_nonimported_procs(
|
|
update_module(size_prof_process_proc_msg(ProgressStream,
|
|
Transform)),
|
|
!HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
MaybeTransform = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_deep_profiling(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_deep_profiling(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.lookup_bool_option(Globals, profile_deep, ProfileDeep),
|
|
(
|
|
ProfileDeep = yes,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Applying deep profiling transformation...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
apply_deep_profiling_transform(ProgressStream, !HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
ProfileDeep = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_experimental_complexity(io.text_output_stream::in,
|
|
bool::in, bool::in, module_info::in, module_info::out,
|
|
io::di, io::uo) is det.
|
|
|
|
maybe_experimental_complexity(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_maybe_complexity_proc_map(!.HLDS, MaybeNumProcMap),
|
|
(
|
|
MaybeNumProcMap = no
|
|
;
|
|
MaybeNumProcMap = yes(NumProcs - ProcMap),
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Applying complexity experiment transformation...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
process_valid_nonimported_procs(
|
|
update_module(complexity_process_proc_msg(ProgressStream,
|
|
NumProcs, ProcMap)),
|
|
!HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_region_analysis(io.text_output_stream::in, bool::in, bool::in,
|
|
module_info::in, module_info::out, io::di, io::uo) is det.
|
|
|
|
maybe_region_analysis(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
Analysis = OptTuple ^ ot_analyse_regions,
|
|
(
|
|
Analysis = analyse_regions,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Analysing regions ...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
do_region_analysis(!HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
Analysis = do_not_analyse_regions
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_eliminate_dead_procs(io.text_output_stream::in,
|
|
bool::in, bool::in, module_info::in, module_info::out,
|
|
io::di, io::uo) is det.
|
|
|
|
maybe_eliminate_dead_procs(ProgressStream, Verbose, Stats, !HLDS, !IO) :-
|
|
module_info_get_globals(!.HLDS, Globals),
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
OptDeadProcs = OptTuple ^ ot_opt_dead_procs,
|
|
(
|
|
OptDeadProcs = opt_dead_procs,
|
|
maybe_write_string(ProgressStream, Verbose,
|
|
"% Eliminating dead procedures...\n", !IO),
|
|
maybe_flush_output(ProgressStream, Verbose, !IO),
|
|
BeforeHLDS = !.HLDS,
|
|
dead_proc_elim(elim_opt_imported, NeededMap, ElimMap, !HLDS),
|
|
maybe_write_string(ProgressStream, Verbose, "% done.\n", !IO),
|
|
globals.lookup_bool_option(Globals, debug_dead_proc_elim,
|
|
DebugDeadProcElim),
|
|
(
|
|
DebugDeadProcElim = no
|
|
;
|
|
DebugDeadProcElim = yes,
|
|
get_debug_output_stream(!.HLDS, DebugStream, !IO),
|
|
output_needed_map(DebugStream, BeforeHLDS, NeededMap, !IO),
|
|
output_elimination_msgs(DebugStream, BeforeHLDS, ElimMap, !IO)
|
|
),
|
|
maybe_report_stats(ProgressStream, Stats, !IO)
|
|
;
|
|
OptDeadProcs = do_not_opt_dead_procs
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module top_level.mercury_compile_middle_passes.
|
|
%---------------------------------------------------------------------------%
|