Files
mercury/compiler/mercury_compile_middle_passes.m
Zoltan Somogyi 2afa32259a Carve four new modules out of unused_args.m.
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.
2026-02-24 02:32:37 +11:00

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