mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-16 18:03:36 +00:00
The motivation for this diff is something I saw when I fixed the bug in
equiv_type_hlds.m on aug 13. During the bootcheck to verify the bug fix,
I enabled the end-of-front-end HLDS dump, and I saw that one module,
deep_profiler/display_report.m, had some references to MISSING_INSTs
in its HLDS dump. Since these could be signs of a bug in mode analysis,
I tracked them down. It turns out that the cause was an incompatibility
between the code that existed in error_msg_inst.m before that fix,
and the new code there added by that fix. But ironically, to find that
incompatibility, I first had to extend error_msg_inst.m's functionality
still further, specifically to make it possible to use it to write out insts
in HLDS dumps.
The reason for this need is that that the old code for dumping out insts
left a lot to be desired. It ignored (as in, it never wrote out) some parts
of specific kinds insts, such as the types in typed insts, without which
some parts of HLDS dumps did not make sense. For example, the ground inst
table in the HLDS dump of display_report.m contained several keys whose
printed versions were identical, seemingly indicating a bug in the code
that added new entries to that table (since it is supposed to add a new entry
to the table if the relevant key does not yet exist in the table). It turns
out that there was no bug; the keys differed, but only in the types.
compiler/error_msg_inst.m:
Fix the incompatibility, and document both it, and its solution.
Besides error_msg_inst, export a new function error_msg_inst_name,
which does the same thing for inst_names as error_msg_inst does for insts.
Add a flag to both functions that specifies whether the intended use
of the return value is in an error message (whose audience is usually
an ordinary Mercury user) or a HLDS dump (whose audience is always
a Mercury developer). Include details such as the types in typed insts,
and the structure of the compiler-generated inst names generally,
which involve concepts that users do not know about, in the output
only if the flag says the audience is Mercury developers.
When printing out type or inst variables, use their actual names
if these are available. To make this possible, require the callers
of error_msg_{inst,inst_name} to provide tvarsets and inst_varsets,
instead of always using empty varsets. The caller may still pass
empty varsets if cannot do better than that, but most callers can,
and now do pass valid varsets.
compiler/hlds_out_goal.m:
Since we now want to pass a valid tvarset to error_msg_inst.m
when printing the insts in goals' instmap_deltas, we need to pass around
the tvarset, as well as the inst_varset, of the procedure that the goal
was taken from. Instead of adding yet another parameter to all the affected
predicates, replace all the existing parameters that have the same role
(of which there were already about half a dozen) with a parameter
of a new type named hlds_out_info_goal, which contains the values of
all these old parameters, and the new one.
compiler/hlds_out_inst_table.m:
Use the same setting to govern whether we use error_msg_inst.m's
facilities for writing out insts and inst names in both the keys
and the values of the various inst tables.
compiler/simplify_info.m:
Include tvarsets in simplify_infos, since dumping out goals during
simplification pass can now use this information.
compiler/add_clause.m:
compiler/add_mutable_aux_preds.m:
compiler/delay_partial_inst.m:
compiler/dep_par_conj.m:
compiler/direct_arg_in_out.m:
compiler/format_call.m:
compiler/goal_expr_to_goal.m:
compiler/hlds_out_pred.m:
compiler/inst_abstract_unify.m:
compiler/inst_lookup.m:
compiler/intermod.m:
compiler/lco.m:
compiler/liveness.m:
compiler/make_hlds_warn.m:
compiler/mode_errors.m:
compiler/pd_debug.m:
compiler/prog_mode.m:
compiler/push_goals_together.m:
compiler/saved_vars.m:
compiler/simplify_goal.m:
compiler/simplify_goal_conj.m:
compiler/simplify_proc.m:
compiler/stack_opt.m:
compiler/superhomogeneous.m:
compiler/unneeded_code.m:
Conform to the changes above.
773 lines
31 KiB
Mathematica
773 lines
31 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_info.m.
|
|
%
|
|
% This module defines the simplify_info type and its access predicates.
|
|
% This contains information for use by the other submodules of simplify.m:
|
|
% both static information (such as identify of the procedure whose body is
|
|
% being simplified), and information specific to the current point in the
|
|
% simplification process (such as the current instmap).
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module check_hlds.simplify.simplify_info.
|
|
:- interface.
|
|
|
|
:- import_module check_hlds.simplify.simplify_tasks.
|
|
:- import_module hlds.
|
|
:- import_module hlds.const_struct.
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module hlds.hlds_rtti.
|
|
:- import_module libs.
|
|
:- import_module libs.optimization_options.
|
|
:- import_module libs.trace_params.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.error_spec.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.var_table.
|
|
|
|
:- import_module bool.
|
|
:- import_module list.
|
|
:- import_module maybe.
|
|
:- import_module set.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type innermost_proc
|
|
---> imp_whole_proc
|
|
% The innermost proc is the whole original procedure.
|
|
; imp_lambda(prog_context).
|
|
% The innermost proc is a lambda expression
|
|
% at the given source location, which a later compiler pass
|
|
% will transform into a separate procedure.
|
|
|
|
% A switch arm context records the fact that we are inside
|
|
% a switch on the given variable, and specifically, we are
|
|
% inside the arm of that switch that is for the given cons_ids.
|
|
:- type switch_arm
|
|
---> switch_arm(
|
|
prog_var,
|
|
set(cons_id)
|
|
).
|
|
|
|
:- type simplify_nested_context
|
|
---> simplify_nested_context(
|
|
% Are we currently inside a goal that was duplicated
|
|
% for a switch?
|
|
snc_inside_dupl_for_switch :: bool,
|
|
|
|
% Can the procedure we are inside be invoked from an
|
|
% all-solutions predicate?
|
|
% If we are inside one or more lambda expressions,
|
|
% the relevant procedure is the innermost lambda,
|
|
% which will later be transformed into a separate procedure.
|
|
% If yes, identify the procedure.
|
|
snc_proc_is_model_non :: maybe(innermost_proc),
|
|
|
|
% Count of the number of lambda goals that
|
|
%
|
|
% - we are inside,
|
|
% - that were not created to implement a try goal.
|
|
%
|
|
% The code of lambda expressions that are created
|
|
% to implement try goals are always executed in the
|
|
% call tree of the procedure in which they appear,
|
|
% but this is not true for lambda expressions in general;
|
|
% they are often returned to ancestors, which then
|
|
% execute them (or not) outside that call tree.
|
|
%
|
|
% If this field is zero, a call that has identical input
|
|
% arguments to the clause head *will* yield an infinite loop;
|
|
% if this field is greater than zero; it only *may* yield
|
|
% an infinite loop.
|
|
snc_num_enclosing_barriers :: uint,
|
|
|
|
% The list of switch arms we are inside. The outermost
|
|
% (and therefore largest, in terms of the amount of code
|
|
% inside it) switch arm will be at the tail end of the list,
|
|
% while the innermost switch arm will be at the head
|
|
% of the list.
|
|
snc_switch_arms :: list(switch_arm)
|
|
).
|
|
|
|
:- type maybe_allow_messages
|
|
---> do_not_allow_messages
|
|
; allow_messages.
|
|
|
|
:- type maybe_rerun_quant_instmap_deltas
|
|
---> do_not_rerun_quant_instmap_deltas
|
|
; rerun_quant_instmap_deltas.
|
|
|
|
:- type maybe_rerun_det
|
|
---> do_not_rerun_det
|
|
; rerun_det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type simplify_info.
|
|
|
|
% Initialise the simplify_info.
|
|
%
|
|
:- pred simplify_info_init(module_info::in, pred_id::in, proc_id::in,
|
|
proc_info::in, simplify_tasks::in, simplify_info::out) is det.
|
|
|
|
% Reinitialise the simplify_info before reprocessing a goal.
|
|
%
|
|
:- pred simplify_info_reinit(simplify_tasks::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Operations on simplify_infos.
|
|
%
|
|
|
|
:- pred simplify_info_get_pred_proc_info(simplify_info::in, pred_info::out,
|
|
proc_info::out) is det.
|
|
|
|
:- pred simplify_info_add_elim_vars(list(prog_var)::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
|
|
:- pred simplify_info_add_message(error_spec::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
|
|
:- pred simplify_info_incr_cost_delta(int::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
|
|
:- pred simplify_info_apply_substitutions_and_duplicate(prog_var::in,
|
|
prog_var::in, tsubst::in, simplify_info::in, simplify_info::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Getters and setters of fields of simplify_info.
|
|
%
|
|
|
|
:- type maybe_fully_strict
|
|
---> not_fully_strict
|
|
; fully_strict.
|
|
|
|
:- type maybe_trace_optimized
|
|
---> not_trace_optimized
|
|
; trace_optimized.
|
|
|
|
:- type maybe_ignore_marked_static
|
|
---> do_not_ignore_marked_static
|
|
; ignore_marked_static.
|
|
|
|
:- pred simplify_info_get_simplify_tasks(simplify_info::in,
|
|
simplify_tasks::out) is det.
|
|
:- pred simplify_info_get_module_info(simplify_info::in, module_info::out)
|
|
is det.
|
|
:- pred simplify_info_get_var_table(simplify_info::in, var_table::out) is det.
|
|
:- pred simplify_info_get_rerun_quant_instmap_delta(simplify_info::in,
|
|
maybe_rerun_quant_instmap_deltas::out) is det.
|
|
:- pred simplify_info_get_rerun_det(simplify_info::in,
|
|
maybe_rerun_det::out) is det.
|
|
|
|
:- pred simplify_info_get_pred_proc_id(simplify_info::in,
|
|
pred_proc_id::out) is det.
|
|
:- pred simplify_info_get_tvarset(simplify_info::in,
|
|
tvarset::out) is det.
|
|
:- pred simplify_info_get_inst_varset(simplify_info::in,
|
|
inst_varset::out) is det.
|
|
:- pred simplify_info_get_fully_strict(simplify_info::in,
|
|
maybe_fully_strict::out) is det.
|
|
:- pred simplify_info_get_eff_trace_level_optimized(simplify_info::in,
|
|
eff_trace_level::out, maybe_trace_optimized::out) is det.
|
|
:- pred simplify_info_get_ignore_marked_static(simplify_info::in,
|
|
maybe_ignore_marked_static::out) is det.
|
|
|
|
:- pred simplify_info_get_rtti_varmaps(simplify_info::in, rtti_varmaps::out)
|
|
is det.
|
|
:- pred simplify_info_get_elim_vars(simplify_info::in,
|
|
list(list(prog_var))::out) is det.
|
|
:- pred simplify_info_get_allow_messages(simplify_info::in,
|
|
maybe_allow_messages::out) is det.
|
|
:- pred simplify_info_get_error_specs(simplify_info::in, list(error_spec)::out)
|
|
is det.
|
|
:- pred simplify_info_get_cost_delta(simplify_info::in, int::out) is det.
|
|
:- pred simplify_info_get_has_parallel_conj(simplify_info::in,
|
|
has_parallel_conj::out) is det.
|
|
:- pred simplify_info_get_found_contains_trace(simplify_info::in, bool::out)
|
|
is det.
|
|
:- pred simplify_info_get_has_user_event(simplify_info::in,
|
|
has_user_event::out) is det.
|
|
:- pred simplify_info_get_deleted_call_callees(simplify_info::in,
|
|
set(pred_proc_id)::out) is det.
|
|
:- pred simplify_info_get_switch_arms_to_split(simplify_info::in,
|
|
set(switch_arm)::out) is det.
|
|
:- pred simplify_info_get_defined_where(simplify_info::in,
|
|
defined_where::out) is det.
|
|
|
|
:- pred simplify_info_set_simplify_tasks(simplify_tasks::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
:- pred simplify_info_set_module_info(module_info::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
:- pred simplify_info_set_var_table(var_table::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
:- pred simplify_info_set_rerun_quant_instmap_delta(
|
|
simplify_info::in, simplify_info::out) is det.
|
|
:- pred simplify_info_set_rerun_det(
|
|
simplify_info::in, simplify_info::out) is det.
|
|
|
|
:- pred simplify_info_set_rtti_varmaps(rtti_varmaps::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
:- pred simplify_info_set_elim_vars(list(list(prog_var))::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
:- pred simplify_info_set_allow_messages(maybe_allow_messages::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
:- pred simplify_info_set_error_specs(list(error_spec)::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
:- pred simplify_info_set_cost_delta(int::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
:- pred simplify_info_set_has_parallel_conj(has_parallel_conj::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
:- pred simplify_info_set_found_contains_trace(bool::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
:- pred simplify_info_set_has_user_event(has_user_event::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
:- pred simplify_info_set_deleted_call_callees(set(pred_proc_id)::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
:- pred simplify_info_set_switch_arms_to_split(set(switch_arm)::in,
|
|
simplify_info::in, simplify_info::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred simplify_do_warn_simple_code(simplify_info::in) is semidet.
|
|
:- pred simplify_do_warn_duplicate_calls(simplify_info::in) is semidet.
|
|
:- pred simplify_do_warn_implicit_stream_calls(simplify_info::in) is semidet.
|
|
:- pred simplify_do_format_calls(simplify_info::in) is semidet.
|
|
:- pred simplify_do_warn_obsolete(simplify_info::in) is semidet.
|
|
:- pred simplify_do_mark_code_model_changes(simplify_info::in) is semidet.
|
|
:- pred simplify_do_after_front_end(simplify_info::in) is semidet.
|
|
:- pred simplify_do_excess_assign(simplify_info::in) is semidet.
|
|
:- pred simplify_do_merge_code_after_switch(simplify_info::in) is semidet.
|
|
:- pred simplify_do_elim_removable_scopes(simplify_info::in) is semidet.
|
|
:- pred simplify_do_opt_duplicate_calls(simplify_info::in) is semidet.
|
|
:- pred simplify_do_const_prop(simplify_info::in) is semidet.
|
|
:- pred simplify_do_ignore_par_conjunctions(simplify_info::in) is semidet.
|
|
:- pred simplify_do_warn_suspicious_recursion(simplify_info::in) is semidet.
|
|
:- pred simplify_do_warn_no_solution_disjunct(simplify_info::in) is semidet.
|
|
|
|
% Succeed if either warn_duplicate_calls or opt_duplicate_calls is set,
|
|
% and return whether opt_duplicate_calls is set.
|
|
%
|
|
:- pred simplify_do_warn_or_opt_duplicate_calls(simplify_info::in,
|
|
maybe_opt_dup_calls::out) is semidet.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module check_hlds.type_util.
|
|
:- import_module hlds.status.
|
|
:- import_module libs.globals.
|
|
:- import_module libs.options.
|
|
|
|
:- import_module int.
|
|
:- import_module map.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% The information we need while we traverse the body of a procedure,
|
|
% simplifying it.
|
|
%
|
|
% The simplify_info, simplify_sub_info and simplify_info_params types
|
|
% constitute a single logical data structure split into three parts
|
|
% for efficiency purposes.
|
|
%
|
|
% The simplify_info type contains the most frequently used writeable
|
|
% fields. The other writeable fields are in the simplify_sub_info,
|
|
% while all the readonly fields are in the simplify_info_params.
|
|
|
|
:- type simplify_info
|
|
---> simplify_info(
|
|
% The Boehm collector allocates blocks whose sizes are
|
|
% multiples of 2, so we should keep the number of fields
|
|
% in a simplify_info to be a multiple of 2 as well.
|
|
|
|
% The tasks we do in this invocation of simplification.
|
|
/* 1 */ simp_simplify_tasks :: simplify_tasks,
|
|
|
|
% The whole module. Those parts of it that are also contained
|
|
% in other fields of simplify_info and simplify_sub_info
|
|
% may be out of date in the module_info.
|
|
/* 2 */ simp_module_info :: module_info,
|
|
|
|
% The variables of the procedure being simplified.
|
|
/* 3 */ simp_var_table :: var_table,
|
|
|
|
% Does the goal need requantification, and the recomputation
|
|
% of instmap_deltas?
|
|
/* 4 */ simp_rerun_quant_instmap_delta
|
|
:: maybe_rerun_quant_instmap_deltas,
|
|
|
|
% Does determinism analysis need to be rerun?
|
|
/* 5 */ simp_rerun_det :: maybe_rerun_det,
|
|
|
|
/* 6 */ simp_params :: simplify_info_params,
|
|
/* 7 */ simp_sub_info :: simplify_sub_info
|
|
).
|
|
|
|
:- type simplify_info_params
|
|
---> simplify_info_params(
|
|
% The id of the procedure we are simplifying, and two
|
|
% fields of its pred_info and proc_info that we need
|
|
% but never change.
|
|
sip_pred_proc_id :: pred_proc_id,
|
|
sip_tvarset :: tvarset,
|
|
sip_inst_varset :: inst_varset,
|
|
|
|
% The value of the --fully-strict option.
|
|
sip_fully_strict :: maybe_fully_strict,
|
|
|
|
sip_eff_trace_level :: eff_trace_level,
|
|
|
|
% The value of the --trace-optimized option.
|
|
sip_trace_optimized :: maybe_trace_optimized,
|
|
|
|
sip_ignore_marked_static :: maybe_ignore_marked_static
|
|
).
|
|
|
|
:- type simplify_sub_info
|
|
---> simplify_sub_info(
|
|
% Information about the typeinfo and typeclass info vars
|
|
% for the type variables of the procedure being simplified.
|
|
% Logically, this field belongs next to simp_var_table,
|
|
% but it is not used frequently enough to store at the
|
|
% top level of simplify_info.
|
|
ssimp_rtti_varmaps :: rtti_varmaps,
|
|
|
|
% The variables we have eliminated. Each list of vars consists
|
|
% of a list of consecutive variable numbers in ascending order.
|
|
% The relative order of the lists is unknown.
|
|
ssimp_elim_vars :: list(list(prog_var)),
|
|
|
|
ssimp_error_specs :: list(error_spec),
|
|
|
|
% Measure of the improvement in the goal from simplification.
|
|
ssimp_cost_delta :: int,
|
|
|
|
% The default value of this field is allow_messages,
|
|
% but it is set to do_not_allow_messages during the second pass
|
|
% of simplification. See the comment in simplify_proc.m
|
|
% next to the call to simplify_info_set_allow_messages
|
|
% for the reason why.
|
|
ssimp_allow_messages :: maybe_allow_messages,
|
|
|
|
% Have we seen a parallel conjunction?
|
|
ssimp_has_parallel_conj :: has_parallel_conj,
|
|
|
|
% Have we seen a goal with a feature that says it contains
|
|
% a trace goal?
|
|
ssimp_found_contains_trace :: bool,
|
|
|
|
% Have we seen an event call?
|
|
ssimp_has_user_event :: has_user_event,
|
|
|
|
% The set of predicates that we deleted calls to while
|
|
% simplifying the procedure body.
|
|
ssimp_deleted_call_callees :: set(pred_proc_id),
|
|
|
|
% The set of outermost switch arm contexts within which
|
|
% there is at least one *other* switch on the same variable.
|
|
% (We collect only the *outermost* switch arms, because when
|
|
% the transformation in split_switch_arms.m processes a switch
|
|
% arm, it also implicitly processes all switches on that
|
|
% same variable inside the code of that arm.)
|
|
ssimp_switch_arms_to_split :: set(switch_arm),
|
|
|
|
% Is the predicate we are simplifying defined in this module?
|
|
ssimp_defined_where :: defined_where
|
|
).
|
|
|
|
simplify_info_init(ModuleInfo, PredId, ProcId, ProcInfo, SimplifyTasks,
|
|
Info) :-
|
|
PredProcId = proc(PredId, ProcId),
|
|
proc_info_get_inst_varset(ProcInfo, InstVarSet),
|
|
module_info_get_globals(ModuleInfo, Globals),
|
|
globals.lookup_bool_option(Globals, fully_strict, FullyStrict0),
|
|
( FullyStrict0 = no, FullyStrict = not_fully_strict
|
|
; FullyStrict0 = yes, FullyStrict = fully_strict
|
|
),
|
|
globals.get_trace_level(Globals, TraceLevel),
|
|
module_info_pred_info(ModuleInfo, PredId, PredInfo),
|
|
pred_info_get_typevarset(PredInfo, TVarSet),
|
|
EffTraceLevel =
|
|
eff_trace_level_for_proc(ModuleInfo, PredInfo, ProcInfo, TraceLevel),
|
|
globals.lookup_bool_option(Globals, trace_optimized, TraceOptimized0),
|
|
( TraceOptimized0 = no, TraceOptimized = not_trace_optimized
|
|
; TraceOptimized0 = yes, TraceOptimized = trace_optimized
|
|
),
|
|
Backend = lookup_current_backend(Globals),
|
|
(
|
|
Backend = low_level_backend,
|
|
IgnoreMarkedStatic = ignore_marked_static
|
|
;
|
|
Backend = high_level_backend,
|
|
IgnoreMarkedStatic = do_not_ignore_marked_static
|
|
),
|
|
|
|
Params = simplify_info_params(PredProcId, TVarSet, InstVarSet, FullyStrict,
|
|
EffTraceLevel, TraceOptimized, IgnoreMarkedStatic),
|
|
|
|
proc_info_get_rtti_varmaps(ProcInfo, RttiVarMaps),
|
|
ElimVars = [],
|
|
AllowMsgs = allow_messages,
|
|
Specs = [],
|
|
CostDelta = 0,
|
|
HasParallelConj = has_no_parallel_conj,
|
|
FoundContainsTrace = no,
|
|
HasUserEvent = has_no_user_event,
|
|
set.init(TraceGoalProcs),
|
|
set.init(SwitchArmsToSplit),
|
|
pred_info_get_status(PredInfo, PredStatus),
|
|
pred_status_defined_in_this_module(PredStatus) = InThisModule,
|
|
( InThisModule = yes, DefinedWhere = defined_in_this_module
|
|
; InThisModule = no, DefinedWhere = defined_in_other_module
|
|
),
|
|
|
|
SubInfo = simplify_sub_info(RttiVarMaps, ElimVars, Specs, CostDelta,
|
|
AllowMsgs, HasParallelConj, FoundContainsTrace, HasUserEvent,
|
|
TraceGoalProcs, SwitchArmsToSplit, DefinedWhere),
|
|
|
|
% SimplifyTasks
|
|
% ModuleInfo
|
|
proc_info_get_var_table(ProcInfo, VarTable),
|
|
RerunQuant = do_not_rerun_quant_instmap_deltas,
|
|
RerunDet = do_not_rerun_det,
|
|
|
|
Info = simplify_info(SimplifyTasks, ModuleInfo, VarTable,
|
|
RerunQuant, RerunDet, Params, SubInfo).
|
|
|
|
simplify_info_reinit(SimplifyTasks, !Info) :-
|
|
!Info ^ simp_simplify_tasks := SimplifyTasks,
|
|
!Info ^ simp_rerun_quant_instmap_delta
|
|
:= do_not_rerun_quant_instmap_deltas,
|
|
!Info ^ simp_rerun_det := do_not_rerun_det,
|
|
!Info ^ simp_sub_info ^ ssimp_has_parallel_conj := has_no_parallel_conj,
|
|
!Info ^ simp_sub_info ^ ssimp_has_user_event := has_no_user_event.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
simplify_info_get_pred_proc_info(Info, PredInfo, ProcInfo) :-
|
|
simplify_info_get_module_info(Info, ModuleInfo),
|
|
simplify_info_get_pred_proc_id(Info, PredProcId),
|
|
module_info_pred_proc_info(ModuleInfo, PredProcId, PredInfo, ProcInfo).
|
|
|
|
simplify_info_add_elim_vars(ElimVars, !Info) :-
|
|
simplify_info_get_elim_vars(!.Info, ElimVarsLists0),
|
|
ElimVarsLists = [ElimVars | ElimVarsLists0],
|
|
simplify_info_set_elim_vars(ElimVarsLists, !Info).
|
|
|
|
simplify_info_add_message(Spec, !Info) :-
|
|
simplify_info_get_allow_messages(!.Info, AllowMsgs),
|
|
(
|
|
AllowMsgs = do_not_allow_messages
|
|
;
|
|
AllowMsgs = allow_messages,
|
|
simplify_info_get_error_specs(!.Info, Specs0),
|
|
Specs = [Spec | Specs0],
|
|
simplify_info_set_error_specs(Specs, !Info)
|
|
).
|
|
|
|
simplify_info_incr_cost_delta(Incr, !Info) :-
|
|
simplify_info_get_cost_delta(!.Info, CostDelta0),
|
|
CostDelta = CostDelta0 + Incr,
|
|
simplify_info_set_cost_delta(CostDelta, !Info).
|
|
|
|
simplify_info_apply_substitutions_and_duplicate(ToVar, FromVar, TSubst,
|
|
!Info) :-
|
|
simplify_info_get_module_info(!.Info, ModuleInfo),
|
|
simplify_info_get_var_table(!.Info, VarTable0),
|
|
simplify_info_get_rtti_varmaps(!.Info, RttiVarMaps0),
|
|
apply_rec_subst_to_var_table(is_type_a_dummy(ModuleInfo), TSubst,
|
|
VarTable0, VarTable),
|
|
Renaming = map.singleton(ToVar, FromVar),
|
|
apply_substitutions_to_rtti_varmaps(map.init, TSubst, Renaming,
|
|
RttiVarMaps0, RttiVarMaps1),
|
|
rtti_var_info_duplicate(FromVar, ToVar, RttiVarMaps1, RttiVarMaps),
|
|
simplify_info_set_var_table(VarTable, !Info),
|
|
simplify_info_set_rtti_varmaps(RttiVarMaps, !Info).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
simplify_info_get_simplify_tasks(Info, X) :-
|
|
X = Info ^ simp_simplify_tasks.
|
|
simplify_info_get_module_info(Info, X) :-
|
|
X = Info ^ simp_module_info.
|
|
simplify_info_get_var_table(Info, X) :-
|
|
X = Info ^ simp_var_table.
|
|
simplify_info_get_rerun_quant_instmap_delta(Info, X) :-
|
|
X = Info ^ simp_rerun_quant_instmap_delta.
|
|
simplify_info_get_rerun_det(Info, X) :-
|
|
X = Info ^ simp_rerun_det.
|
|
|
|
simplify_info_get_pred_proc_id(Info, X) :-
|
|
X = Info ^ simp_params ^ sip_pred_proc_id.
|
|
simplify_info_get_tvarset(Info, X) :-
|
|
X = Info ^ simp_params ^ sip_tvarset.
|
|
simplify_info_get_inst_varset(Info, X) :-
|
|
X = Info ^ simp_params ^ sip_inst_varset.
|
|
simplify_info_get_fully_strict(Info, X) :-
|
|
X = Info ^ simp_params ^ sip_fully_strict.
|
|
simplify_info_get_eff_trace_level_optimized(Info, X, Y) :-
|
|
X = Info ^ simp_params ^ sip_eff_trace_level,
|
|
Y = Info ^ simp_params ^ sip_trace_optimized.
|
|
simplify_info_get_ignore_marked_static(Info, X) :-
|
|
X = Info ^ simp_params ^ sip_ignore_marked_static.
|
|
|
|
simplify_info_get_rtti_varmaps(Info, X) :-
|
|
X = Info ^ simp_sub_info ^ ssimp_rtti_varmaps.
|
|
simplify_info_get_elim_vars(Info, X) :-
|
|
X = Info ^ simp_sub_info ^ ssimp_elim_vars.
|
|
simplify_info_get_allow_messages(Info, X) :-
|
|
X = Info ^ simp_sub_info ^ ssimp_allow_messages.
|
|
simplify_info_get_error_specs(Info, X) :-
|
|
X = Info ^ simp_sub_info ^ ssimp_error_specs.
|
|
simplify_info_get_cost_delta(Info, X) :-
|
|
X = Info ^ simp_sub_info ^ ssimp_cost_delta.
|
|
simplify_info_get_has_parallel_conj(Info, X) :-
|
|
X = Info ^ simp_sub_info ^ ssimp_has_parallel_conj.
|
|
simplify_info_get_found_contains_trace(Info, X) :-
|
|
X = Info ^ simp_sub_info ^ ssimp_found_contains_trace.
|
|
simplify_info_get_has_user_event(Info, X) :-
|
|
X = Info ^ simp_sub_info ^ ssimp_has_user_event.
|
|
simplify_info_get_deleted_call_callees(Info, X) :-
|
|
X = Info ^ simp_sub_info ^ ssimp_deleted_call_callees.
|
|
simplify_info_get_switch_arms_to_split(Info, X) :-
|
|
X = Info ^ simp_sub_info ^ ssimp_switch_arms_to_split.
|
|
simplify_info_get_defined_where(Info, X) :-
|
|
X = Info ^ simp_sub_info ^ ssimp_defined_where.
|
|
|
|
%---------------------%
|
|
|
|
simplify_info_set_simplify_tasks(X, !Info) :-
|
|
!Info ^ simp_simplify_tasks := X.
|
|
simplify_info_set_module_info(X, !Info) :-
|
|
( if private_builtin.pointer_equal(X, !.Info ^ simp_module_info) then
|
|
true
|
|
else
|
|
!Info ^ simp_module_info := X
|
|
).
|
|
simplify_info_set_var_table(X, !Info) :-
|
|
( if private_builtin.pointer_equal(X, !.Info ^ simp_var_table) then
|
|
true
|
|
else
|
|
!Info ^ simp_var_table := X
|
|
).
|
|
simplify_info_set_rerun_quant_instmap_delta(!Info) :-
|
|
X = rerun_quant_instmap_deltas,
|
|
( if X = !.Info ^ simp_rerun_quant_instmap_delta then
|
|
true
|
|
else
|
|
!Info ^ simp_rerun_quant_instmap_delta := X
|
|
).
|
|
simplify_info_set_rerun_det(!Info) :-
|
|
X = rerun_det,
|
|
( if X = !.Info ^ simp_rerun_det then
|
|
true
|
|
else
|
|
!Info ^ simp_rerun_det := X
|
|
).
|
|
|
|
simplify_info_set_rtti_varmaps(X, !Info) :-
|
|
( if
|
|
private_builtin.pointer_equal(X,
|
|
!.Info ^ simp_sub_info ^ ssimp_rtti_varmaps)
|
|
then
|
|
true
|
|
else
|
|
!Info ^ simp_sub_info ^ ssimp_rtti_varmaps := X
|
|
).
|
|
simplify_info_set_elim_vars(X, !Info) :-
|
|
!Info ^ simp_sub_info ^ ssimp_elim_vars := X.
|
|
simplify_info_set_allow_messages(X, !Info) :-
|
|
!Info ^ simp_sub_info ^ ssimp_allow_messages := X.
|
|
simplify_info_set_error_specs(X, !Info) :-
|
|
!Info ^ simp_sub_info ^ ssimp_error_specs := X.
|
|
simplify_info_set_cost_delta(X, !Info) :-
|
|
( if X = !.Info ^ simp_sub_info ^ ssimp_cost_delta then
|
|
true
|
|
else
|
|
!Info ^ simp_sub_info ^ ssimp_cost_delta := X
|
|
).
|
|
simplify_info_set_has_parallel_conj(X, !Info) :-
|
|
( if X = !.Info ^ simp_sub_info ^ ssimp_has_parallel_conj then
|
|
true
|
|
else
|
|
!Info ^ simp_sub_info ^ ssimp_has_parallel_conj := X
|
|
).
|
|
simplify_info_set_found_contains_trace(X, !Info) :-
|
|
( if X = !.Info ^ simp_sub_info ^ ssimp_found_contains_trace then
|
|
true
|
|
else
|
|
!Info ^ simp_sub_info ^ ssimp_found_contains_trace := X
|
|
).
|
|
simplify_info_set_has_user_event(X, !Info) :-
|
|
( if X = !.Info ^ simp_sub_info ^ ssimp_has_user_event then
|
|
true
|
|
else
|
|
!Info ^ simp_sub_info ^ ssimp_has_user_event := X
|
|
).
|
|
simplify_info_set_deleted_call_callees(X, !Info) :-
|
|
( if
|
|
private_builtin.pointer_equal(X,
|
|
!.Info ^ simp_sub_info ^ ssimp_deleted_call_callees)
|
|
then
|
|
true
|
|
else
|
|
!Info ^ simp_sub_info ^ ssimp_deleted_call_callees := X
|
|
).
|
|
simplify_info_set_switch_arms_to_split(X, !Info) :-
|
|
!Info ^ simp_sub_info ^ ssimp_switch_arms_to_split := X.
|
|
|
|
% Access stats for the det_info structure, derived on 2017 march 8
|
|
% using the commented-out code below:
|
|
%
|
|
% i read same diff same%
|
|
% 0 54320730 0 428653 0.00% simplify_tasks
|
|
% 1 22537405 10190586 39961 99.61% module_info
|
|
% 2 1164463 29082 87284 24.99% varset
|
|
% 3 11655215 103357 14630 87.60% vartypes
|
|
% 4 593952 34444 81741 29.65% rtti_varmaps
|
|
% 5 144530 0 0 fully_strict
|
|
% 6 1268871 0 0 pred_id, proc_id
|
|
% 7 25167 0 0 inst_varset
|
|
% 8 431612 0 4700 0.00% elim_vars
|
|
% 9 8132 0 428653 0.00% allow_messages
|
|
% 10 431084 0 4172 0.00% error_specs
|
|
% 11 858622 41608 25167 62.31% requantify
|
|
% 12 858622 531 1606 24.85% rerun_det
|
|
% 13 148274 83477 61740 57.48% cost_delta
|
|
% 14 426912 52 170 23.42% has_parallel_conj
|
|
% 15 429969 8066 887 90.09% found_contains_trace
|
|
% 16 426912 16 36 30.77% has_user_event
|
|
% 17 484085 56008 1165 97.96% deleted_call_callees
|
|
%
|
|
% :- pragma foreign_decl("C", local,
|
|
% "
|
|
% #define MR_NUM_INFO_STATS 18
|
|
% unsigned long MR_stats_read[MR_NUM_INFO_STATS];
|
|
% unsigned long MR_stats_same[MR_NUM_INFO_STATS];
|
|
% unsigned long MR_stats_diff[MR_NUM_INFO_STATS];
|
|
% ").
|
|
%
|
|
% :- pred gather_info_read_stats(int::in,
|
|
% T::in, T::out) is det.
|
|
%
|
|
% :- pragma foreign_proc("C",
|
|
% gather_info_read_stats(N::in, X0::in, X::out),
|
|
% [will_not_call_mercury, promise_pure],
|
|
% "
|
|
% ++MR_stats_read[N];
|
|
% X = X0;
|
|
% ").
|
|
%
|
|
% :- pred gather_info_write_stats(int::in, T::in, T::in,
|
|
% simplify_info::in, simplify_info::out) is det.
|
|
%
|
|
% :- pragma foreign_proc("C",
|
|
% gather_info_write_stats(N::in, Old::in, New::in, Info0::in, Info::out),
|
|
% [will_not_call_mercury, promise_pure],
|
|
% "
|
|
% if (((MR_Unsigned) Old) == ((MR_Unsigned) New)) {
|
|
% ++MR_stats_same[N];
|
|
% } else {
|
|
% ++MR_stats_diff[N];
|
|
% }
|
|
%
|
|
% Info = Info0;
|
|
% ").
|
|
%
|
|
% :- interface.
|
|
% :- import_module io.
|
|
% :- pred write_simplify_info_stats(io::di, io::uo) is det.
|
|
% :- implementation.
|
|
%
|
|
% :- pragma foreign_proc("C",
|
|
% write_simplify_info_stats(IO0::di, IO::uo),
|
|
% [will_not_call_mercury, promise_pure],
|
|
% "
|
|
% FILE *fp;
|
|
%
|
|
% fp = fopen(""/tmp/SIMPLIFY_INFO_STATS"", ""a"");
|
|
% if (fp != NULL) {
|
|
% int i;
|
|
% for (i = 0; i < MR_NUM_INFO_STATS; i++) {
|
|
% fprintf(fp, ""stat_rsd %d %lu %lu %lu\\n"",
|
|
% i, MR_stats_read[i], MR_stats_same[i], MR_stats_diff[i]);
|
|
% }
|
|
% }
|
|
%
|
|
% IO = IO0;
|
|
% ").
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
simplify_do_warn_simple_code(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_warn_simple_code = warn_simple_code.
|
|
simplify_do_warn_duplicate_calls(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_warn_duplicate_calls = warn_duplicate_calls.
|
|
simplify_do_warn_implicit_stream_calls(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_warn_implicit_streams = warn_implicit_streams.
|
|
simplify_do_format_calls(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_invoke_format_call = invoke_format_call.
|
|
simplify_do_warn_obsolete(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_warn_obsolete = warn_obsolete.
|
|
simplify_do_mark_code_model_changes(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_mark_code_model_changes = mark_code_model_changes.
|
|
simplify_do_after_front_end(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_after_front_end = after_front_end.
|
|
simplify_do_excess_assign(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_excess_assign = elim_excess_assigns.
|
|
simplify_do_merge_code_after_switch(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_merge_code_after_switch = merge_code_after_switch.
|
|
simplify_do_elim_removable_scopes(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_elim_removable_scopes = elim_removable_scopes.
|
|
simplify_do_opt_duplicate_calls(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_opt_duplicate_calls = opt_dup_calls.
|
|
simplify_do_const_prop(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_constant_prop = prop_constants.
|
|
simplify_do_ignore_par_conjunctions(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_ignore_par_conjunctions = ignore_par_conjs.
|
|
simplify_do_warn_suspicious_recursion(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_warn_suspicious_recursion = warn_suspicious_rec.
|
|
simplify_do_warn_no_solution_disjunct(Info) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
SimplifyTasks ^ do_warn_no_solution_disjunct = warn_no_soln_disjunct.
|
|
|
|
simplify_do_warn_or_opt_duplicate_calls(Info, OptDuplicateCalls) :-
|
|
simplify_info_get_simplify_tasks(Info, SimplifyTasks),
|
|
WarnDuplicateCalls = SimplifyTasks ^ do_warn_duplicate_calls,
|
|
OptDuplicateCalls = SimplifyTasks ^ do_opt_duplicate_calls,
|
|
( WarnDuplicateCalls = warn_duplicate_calls
|
|
; OptDuplicateCalls = opt_dup_calls
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module check_hlds.simplify.simplify_info.
|
|
%---------------------------------------------------------------------------%
|