mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-19 19:33:46 +00:00
This implements Mantis feature request #495. NEWS: Announce the change. compiler/optimization_options.m: A new module for managing optimization options. It defines a separate bespoke type for every boolean optimization option to make it harder to confuse them. It defines a tuple type (opt_tuple) for accessing optimization options quickly. It implements the turning on (but NOT turning off) of optimizations when a given optimization level is selected. tools/make_optimization_options_middle: tools/make_optimization_options_db: The script that generates the meat of optimization_options.m, and the database of option names, kinds and initial values that it uses as its input. The script also generates some code for the special_handler predicate in compiler/options.m. tools/make_optimization_options_start: tools/make_optimization_options_end: The handwritten initial and final parts of optimization_options.m. tools/make_optimization_options: The script that pulls these parts together to form optimization_options.m. compiler/options.m: Make every optimization option a special option, to be handled by the special_handler predicate. That handling consists of simply adding a representation of the option to the end of a cord of optimization options, to be processed later by optimization_options.m. That processing will record the values of these options in the opt_tuple, which is where every other part of the compiler should get them from. Change the interface of special_handler to make the above possible. Add an "optopt_" (optimization option) prefix to the name of every optimization option, to make them inaccessible to the rest of the compiler under their old name, and thus help enforce the switch to using the opt_tuple. Any access to these options to look up their values would fail anyway, since the option data would no longer be e.g. bool(yes), but bool_special, but the name change makes this failure happen at compile time, not runtime. Reclassify a few options to make the above make sense. Some options (unneeded_code_debug, unneeded_code_debug_pred_name, and common_struct_preds) were classified as oc_opt even though they control only the *debugging* of optimizations, while some options (c_optimize and inline_alloc) were not classified as oc_opt even though we do set them automatically at some optimization levels. Delete the opt_level_number option, since it was not used anywhere. Delete the code for handling -ON and --opt-space, since that is now done in optimization_options.m. Add some XXXs. compiler/handle_options.m: Switch to using getopt_io.process_options_userdata_se, as required by the new interface of the special_handler in options.m. In the absence of errors, invoke optimization_options.m to initialize the opt_tuple. Then update the opt_tuple incrementally when processing option implications that affect optimization options. compiler/globals.m: Put the opt_tuple into a new field of the globals structure. compiler/accumulator.m: compiler/add_pragma_type_spec.m: compiler/add_trail_ops.m: compiler/code_info.m: compiler/code_loc_dep.m: compiler/compile_target_code.m: compiler/const_struct.m: compiler/deforest.m: compiler/dep_par_conj.m: compiler/disj_gen.m: compiler/erl_code_gen.m: compiler/format_call.m: compiler/global_data.m: compiler/grab_modules.m: compiler/higher_order.m: compiler/hlds_pred.m: compiler/inlining.m: compiler/intermod.m: compiler/ite_gen.m: compiler/jumpopt.m: compiler/libs.m: compiler/llds_out_code_addr.m: compiler/llds_out_data.m: compiler/llds_out_file.m: compiler/llds_out_instr.m: compiler/llds_out_util.m: compiler/matching.m: compiler/mercury_compile_front_end.m: compiler/mercury_compile_llds_back_end.m: compiler/mercury_compile_main.m: compiler/mercury_compile_middle_passes.m: compiler/mercury_compile_mlds_back_end.m: compiler/ml_disj_gen.m: compiler/ml_gen_info.m: compiler/ml_lookup_switch.m: compiler/ml_optimize.m: compiler/ml_proc_gen.m: compiler/ml_simplify_switch.m: compiler/ml_switch_gen.m: compiler/ml_unify_gen_construct.m: compiler/optimize.m: compiler/pd_util.m: compiler/peephole.m: compiler/polymorphism.m: compiler/proc_gen.m: compiler/simplify_goal_call.m: compiler/simplify_goal_scope.m: compiler/simplify_info.m: compiler/simplify_proc.m: compiler/simplify_tasks.m: compiler/stack_layout.m: compiler/stack_opt.m: compiler/switch_gen.m: compiler/switch_util.m: compiler/tag_switch.m: compiler/tupling.m: compiler/unify_gen_construct.m: compiler/unneeded_code.m: compiler/unused_args.m: Conform to the changes above, mostly by looking up optimization options in the opt_tuple. In some places, replace bools containing optimization options with the bespoke type of that specific optimization option. library/getopt_template: Fix a bug that screwed up an error message. The bug happened when processing a --file option. If one of the options in the file was a special option whose special handler failed, the code handling that failing option returned both an error indication, and the rest of the argument list read in from the file. The code handling the --file option then *ignored* the error indication from the failed special option, and returned an error message of its own complaining about the unconsumed remaining arguments in the file, believing them to be non-option arguments, even though these arguments were never looked it to see if they were options. The fix is for the code handling --flag options to check whether the code processing the file contents found any errors, and if so, return that error *without* looking at the list of remaining arguments. In an unrelated change, factor out a duplicate call.
270 lines
12 KiB
Mathematica
270 lines
12 KiB
Mathematica
%----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%----------------------------------------------------------------------------%
|
|
% Copyright (C) 2014 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: simplify_tasks.m.
|
|
%
|
|
% This module handles the specification of what tasks the submodules of
|
|
% simplify.m should perform.
|
|
%
|
|
%----------------------------------------------------------------------------%
|
|
|
|
:- module check_hlds.simplify.simplify_tasks.
|
|
:- interface.
|
|
|
|
:- import_module libs.
|
|
:- import_module libs.globals.
|
|
:- import_module libs.optimization_options.
|
|
|
|
:- import_module bool.
|
|
:- import_module list.
|
|
|
|
% Each value of this type represents a task, or a group of related tasks,
|
|
% that simplification should perform.
|
|
:- type simplify_task
|
|
---> simptask_warn_simple_code
|
|
% --warn-simple-code
|
|
|
|
; simptask_warn_duplicate_calls
|
|
% --warn-duplicate-calls
|
|
|
|
; simptask_warn_implicit_stream_calls
|
|
% --warn-implicit-stream-calls
|
|
|
|
; simptask_format_calls
|
|
% Invoke format_call.m.
|
|
|
|
; simptask_warn_obsolete
|
|
% --warn-obsolete
|
|
|
|
; simptask_mark_code_model_changes
|
|
% Some compiler passes generate HLDS in which changes in code model
|
|
% are implicit in the determinisms stored in the goal_infos of
|
|
% nested goals (such as a conjunction without outputs being
|
|
% semidet, and some conjuncts being nondet). Make these code model
|
|
% changes visible by adding a scope wrapper.
|
|
|
|
; simptask_after_front_end
|
|
% Do the tasks that should be done at the end of the front end.
|
|
|
|
; simptask_excess_assigns
|
|
% Remove excess assignment unifications.
|
|
|
|
; simptask_test_after_switch
|
|
% Optimize away test unifications after switches whose arms
|
|
% do nothing except set the to-be-tested variable.
|
|
|
|
; simptask_elim_removable_scopes
|
|
% Remove scopes that do not need processing during LLDS code
|
|
% generation.
|
|
|
|
; simptask_opt_duplicate_calls
|
|
% Optimize duplicate calls.
|
|
|
|
; simptask_constant_prop
|
|
% Partially evaluate calls.
|
|
|
|
; simptask_common_struct
|
|
% Common structure elimination.
|
|
|
|
; simptask_extra_common_struct
|
|
% Do common structure elimination even when it might
|
|
% increase stack usage (used by deforestation).
|
|
|
|
; simptask_ignore_par_conjs
|
|
% Replace parallel conjunctions with plain conjunctions.
|
|
|
|
; simptask_warn_suspicious_recursion
|
|
% With simptask_warn_simple_code, we generate warnings
|
|
% for recursive calls in which all input arguments are
|
|
% the same as in the clause head. These calls are guaranteed
|
|
% to represent an infinite loop.
|
|
%
|
|
% If simptask_warn_suspicious_recursion is also set, we also
|
|
% generate a weaker version of that warning for recursive calls
|
|
% in which all *non-state-var* input arguments are the same as
|
|
% in the clause head. In the usual case where the recursion is
|
|
% controlled by the non-state-var input arguments, these calls
|
|
% also represent an infinite loop, but we cannot say that for
|
|
% certain, because in some cases, the predicate is recursing
|
|
% on a data structure that the code *does* refer to using
|
|
% state variable notation.
|
|
|
|
; simptask_warn_no_solution_disjunct.
|
|
% Warn about disjuncts that can have no solution.
|
|
|
|
% Each value of this type represents the full set of tasks
|
|
% that simplification should perform. The submodules of simplify.m
|
|
% use it to find out whether they should perform a specific task
|
|
% without having to search a list of simplifications.
|
|
%
|
|
% The definition of this type does not need to be visible to modules
|
|
% outside simplify.m, but avoiding such visibility would cost more
|
|
% in extra complexity than it would gain.
|
|
:- type simplify_tasks
|
|
---> simplify_tasks(
|
|
do_warn_simple_code :: bool,
|
|
do_warn_duplicate_calls :: bool,
|
|
do_warn_implicit_stream_calls :: bool,
|
|
do_format_calls :: bool,
|
|
do_warn_obsolete :: bool,
|
|
do_mark_code_model_changes :: bool,
|
|
do_after_front_end :: bool,
|
|
do_excess_assign :: maybe_elim_excess_assigns,
|
|
do_test_after_switch :: maybe_opt_test_after_switch,
|
|
do_elim_removable_scopes :: bool,
|
|
do_opt_duplicate_calls :: maybe_opt_dup_calls,
|
|
do_constant_prop :: maybe_prop_constants,
|
|
do_common_struct :: maybe_opt_common_structs,
|
|
do_extra_common_struct :: bool,
|
|
do_ignore_par_conjunctions :: bool,
|
|
do_warn_suspicious_recursion :: bool,
|
|
do_warn_no_solution_disjunct :: bool
|
|
).
|
|
|
|
:- func simplify_tasks_to_list(simplify_tasks) = list(simplify_task).
|
|
:- func list_to_simplify_tasks(list(simplify_task)) = simplify_tasks.
|
|
|
|
% Find out which simplifications should be run from the options table
|
|
% stored in the globals. The first argument states whether warnings
|
|
% should be issued during this pass of simplification.
|
|
%
|
|
:- pred find_simplify_tasks(bool::in, globals::in, simplify_tasks::out) is det.
|
|
|
|
%----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module libs.options.
|
|
|
|
simplify_tasks_to_list(SimplifyTasks) = List :-
|
|
SimplifyTasks = simplify_tasks(WarnSimpleCode, WarnDupCalls,
|
|
WarnImplicitStreamCalls, DoFormatCalls, WarnObsolete,
|
|
MarkCodeModelChanges, AfterFrontEnd, ExcessAssign, TestAfterSwitch,
|
|
ElimRemovableScopes, OptDuplicateCalls, ConstantProp,
|
|
CommonStruct, ExtraCommonStruct, RemoveParConjunctions,
|
|
WarnSuspiciousRecursion, WarnNoSolutionDisjunct),
|
|
List =
|
|
( WarnSimpleCode = yes -> [simptask_warn_simple_code] ; [] ) ++
|
|
( WarnDupCalls = yes -> [simptask_warn_duplicate_calls] ; [] ) ++
|
|
( WarnImplicitStreamCalls = yes ->
|
|
[simptask_warn_implicit_stream_calls] ; [] ) ++
|
|
( DoFormatCalls = yes -> [simptask_format_calls] ; [] ) ++
|
|
( WarnObsolete = yes -> [simptask_warn_obsolete] ; [] ) ++
|
|
( MarkCodeModelChanges = yes ->
|
|
[simptask_mark_code_model_changes] ; [] ) ++
|
|
( AfterFrontEnd = yes -> [simptask_after_front_end] ; [] ) ++
|
|
( ExcessAssign = elim_excess_assigns ->
|
|
[simptask_excess_assigns] ; [] ) ++
|
|
( TestAfterSwitch = opt_test_after_switch ->
|
|
[simptask_test_after_switch] ; [] ) ++
|
|
( ElimRemovableScopes = yes ->
|
|
[simptask_elim_removable_scopes] ; [] ) ++
|
|
( OptDuplicateCalls = opt_dup_calls ->
|
|
[simptask_opt_duplicate_calls] ; [] ) ++
|
|
( ConstantProp = prop_constants -> [simptask_constant_prop] ; [] ) ++
|
|
( CommonStruct = opt_common_structs ->
|
|
[simptask_common_struct] ; [] ) ++
|
|
( ExtraCommonStruct = yes -> [simptask_extra_common_struct] ; [] ) ++
|
|
( RemoveParConjunctions = yes -> [simptask_ignore_par_conjs] ; [] ) ++
|
|
( WarnSuspiciousRecursion = yes ->
|
|
[simptask_warn_suspicious_recursion] ; [] ) ++
|
|
( WarnNoSolutionDisjunct = yes ->
|
|
[simptask_warn_no_solution_disjunct] ; [] ).
|
|
|
|
list_to_simplify_tasks(List) =
|
|
simplify_tasks(
|
|
( list.member(simptask_warn_simple_code, List) -> yes ; no ),
|
|
( list.member(simptask_warn_duplicate_calls, List) -> yes ; no ),
|
|
( list.member(simptask_warn_implicit_stream_calls, List) -> yes ; no ),
|
|
( list.member(simptask_format_calls, List) -> yes ; no ),
|
|
( list.member(simptask_warn_obsolete, List) -> yes ; no ),
|
|
( list.member(simptask_mark_code_model_changes, List) -> yes ; no ),
|
|
( list.member(simptask_after_front_end, List) -> yes ; no ),
|
|
( list.member(simptask_excess_assigns, List) ->
|
|
elim_excess_assigns ; do_not_elim_excess_assigns ),
|
|
( list.member(simptask_test_after_switch, List) ->
|
|
opt_test_after_switch ; do_not_opt_test_after_switch ),
|
|
( list.member(simptask_elim_removable_scopes, List) -> yes ; no ),
|
|
( list.member(simptask_opt_duplicate_calls, List) ->
|
|
opt_dup_calls ; do_not_opt_dup_calls ),
|
|
( list.member(simptask_constant_prop, List) ->
|
|
prop_constants ; do_not_prop_constants ),
|
|
( list.member(simptask_common_struct, List) ->
|
|
opt_common_structs ; do_not_opt_common_structs ),
|
|
( list.member(simptask_extra_common_struct, List) -> yes ; no ),
|
|
( list.member(simptask_ignore_par_conjs, List) -> yes ; no ),
|
|
( list.member(simptask_warn_suspicious_recursion, List) -> yes ; no ),
|
|
( list.member(simptask_warn_no_solution_disjunct, List) -> yes ; no )
|
|
).
|
|
|
|
find_simplify_tasks(WarnThisPass, Globals, SimplifyTasks) :-
|
|
globals.lookup_bool_option(Globals, warn_simple_code, WarnSimple),
|
|
globals.lookup_bool_option(Globals, warn_duplicate_calls, WarnDupCalls),
|
|
globals.lookup_bool_option(Globals, warn_implicit_stream_calls,
|
|
WarnImplicitStreamCalls),
|
|
globals.lookup_bool_option(Globals, warn_known_bad_format_calls,
|
|
WarnKnownBadFormat),
|
|
globals.lookup_bool_option(Globals, warn_unknown_format_calls,
|
|
WarnUnknownFormat),
|
|
globals.get_opt_tuple(Globals, OptTuple),
|
|
OptFormatCalls = OptTuple ^ ot_opt_format_calls,
|
|
( if
|
|
(
|
|
WarnThisPass = yes,
|
|
( WarnKnownBadFormat = yes ; WarnUnknownFormat = yes )
|
|
;
|
|
OptFormatCalls = opt_format_calls
|
|
)
|
|
then
|
|
DoFormatCalls = yes
|
|
else
|
|
DoFormatCalls = no
|
|
),
|
|
globals.lookup_bool_option(Globals, warn_obsolete, WarnObsolete),
|
|
ExcessAssign = OptTuple ^ ot_elim_excess_assigns,
|
|
TestAfterSwitch = OptTuple ^ ot_opt_test_after_switch,
|
|
CommonStruct = OptTuple ^ ot_opt_common_structs,
|
|
OptDuplicateCalls = OptTuple ^ ot_opt_dup_calls,
|
|
ConstantProp = OptTuple ^ ot_prop_constants,
|
|
MarkCodeModelChanges = no,
|
|
AfterFrontEnd = no,
|
|
ElimRemovableScopes = no,
|
|
ExtraCommonStruct = no,
|
|
globals.lookup_bool_option(Globals, ignore_par_conjunctions,
|
|
RemoveParConjunctions),
|
|
globals.lookup_bool_option(Globals, warn_suspicious_recursion,
|
|
WarnSuspiciousRecursion),
|
|
% Warnings about "no solution disjuncts" are a category of warnings
|
|
% about simple code that happens to have its own disabling mechanism.
|
|
WarnNoSolutionDisjunct = WarnSimple,
|
|
|
|
SimplifyTasks = simplify_tasks(
|
|
( if WarnSimple = yes, WarnThisPass = yes then yes else no),
|
|
( if WarnDupCalls = yes, WarnThisPass = yes then yes else no),
|
|
( if WarnImplicitStreamCalls = yes, WarnThisPass = yes
|
|
then yes else no),
|
|
DoFormatCalls,
|
|
( if WarnObsolete = yes, WarnThisPass = yes then yes else no),
|
|
MarkCodeModelChanges,
|
|
AfterFrontEnd,
|
|
ExcessAssign,
|
|
TestAfterSwitch,
|
|
ElimRemovableScopes,
|
|
OptDuplicateCalls,
|
|
ConstantProp,
|
|
CommonStruct,
|
|
ExtraCommonStruct,
|
|
RemoveParConjunctions,
|
|
WarnSuspiciousRecursion,
|
|
WarnNoSolutionDisjunct
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module check_hlds.simplify.simplify_tasks.
|
|
%---------------------------------------------------------------------------%
|