mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-14 13:23:53 +00:00
Estimated hours taken: 2 Branches: main, release Make the system compiler with --warn-unused-imports. browser/*.m: library/*.m: compiler/*.m: Remove unnecesary imports as flagged by --warn-unused-imports. In some files, do some minor cleanup along the way.
299 lines
10 KiB
Mathematica
299 lines
10 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2006-2010 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: structure_reuse.direct.m.
|
|
% Main authors: nancy.
|
|
%
|
|
% This module defines procedures and types related to the detection of so
|
|
% called "direct reuses" within the CTGC system. A direct reuse is a
|
|
% combination of the location of a deconstruction unification (where a
|
|
% datastructure may become garbage under certain conditions) and a set of
|
|
% locations of construction unifications where the garbage datastructure can
|
|
% be reused locally.
|
|
%
|
|
% Direct reuse analysis requires two steps:
|
|
% - Detecting where datastructures may become garbage.
|
|
% - Finding where these garbage datastructures can be reused.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module transform_hlds.ctgc.structure_reuse.direct.
|
|
:- interface.
|
|
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module transform_hlds.ctgc.structure_reuse.domain.
|
|
:- import_module transform_hlds.ctgc.structure_sharing.domain.
|
|
|
|
:- import_module list.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% The first pass, where we process all procedures defined in the module.
|
|
%
|
|
:- pred direct_reuse_pass(sharing_as_table::in,
|
|
module_info::in, module_info::out,
|
|
reuse_as_table::in, reuse_as_table::out) is det.
|
|
|
|
% Subsequent passes, where we process only the listed procedures.
|
|
%
|
|
:- pred direct_reuse_process_specific_procs(sharing_as_table::in,
|
|
list(pred_proc_id)::in, module_info::in, module_info::out,
|
|
reuse_as_table::in, reuse_as_table::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module analysis.
|
|
:- import_module hlds.passes_aux.
|
|
:- import_module libs.file_util.
|
|
:- import_module libs.globals.
|
|
:- import_module libs.options.
|
|
:- import_module transform_hlds.ctgc.structure_reuse.direct.choose_reuse.
|
|
:- import_module transform_hlds.ctgc.structure_reuse.direct.detect_garbage.
|
|
:- import_module transform_hlds.ctgc.util.
|
|
:- import_module transform_hlds.smm_common.
|
|
|
|
:- import_module bool.
|
|
:- import_module io.
|
|
:- import_module map.
|
|
:- import_module svmap.
|
|
|
|
:- include_module transform_hlds.ctgc.structure_reuse.direct.detect_garbage.
|
|
:- include_module transform_hlds.ctgc.structure_reuse.direct.choose_reuse.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
direct_reuse_pass(SharingTable, !ModuleInfo, !ReuseTable) :-
|
|
% Gather the pred_ids of the preds that need to be analysed.
|
|
module_info_get_valid_predids(AllPredIds, !ModuleInfo),
|
|
list.filter(pred_requires_analysis(!.ModuleInfo), AllPredIds,
|
|
ToBeAnalysedPredIds),
|
|
|
|
% Analyse and annotate each of the predicates.
|
|
list.foldl2(direct_reuse_process_pred(SharingTable), ToBeAnalysedPredIds,
|
|
!ModuleInfo, !ReuseTable).
|
|
|
|
:- pred direct_reuse_process_pred(sharing_as_table::in, pred_id::in,
|
|
module_info::in, module_info::out,
|
|
reuse_as_table::in, reuse_as_table::out) is det.
|
|
|
|
direct_reuse_process_pred(SharingTable, PredId, !ModuleInfo, !ReuseTable) :-
|
|
module_info_pred_info(!.ModuleInfo, PredId, PredInfo0),
|
|
(
|
|
pred_info_get_origin(PredInfo0, Origin),
|
|
Origin = origin_special_pred(_)
|
|
->
|
|
% We can't analyse compiler generated special predicates.
|
|
true
|
|
;
|
|
pred_info_get_import_status(PredInfo0, status_external(_))
|
|
->
|
|
% We can't analyse `:- external' predicates but add an extry to the
|
|
% reuse table so something will be written out to optimisation
|
|
% interface files.
|
|
list.foldl(
|
|
set_external_pred_reuse_as(PredId, reuse_as_init, optimal),
|
|
pred_info_procids(PredInfo0), !ReuseTable)
|
|
;
|
|
ProcIds = pred_info_non_imported_procids(PredInfo0),
|
|
list.foldl2(direct_reuse_process_proc(SharingTable, PredId),
|
|
ProcIds, !ModuleInfo, !ReuseTable)
|
|
).
|
|
|
|
:- pred set_external_pred_reuse_as(pred_id::in, reuse_as::in,
|
|
analysis_status::in, proc_id::in, reuse_as_table::in, reuse_as_table::out)
|
|
is det.
|
|
|
|
set_external_pred_reuse_as(PredId, ReuseAs, Status, ProcId, !ReuseTable) :-
|
|
reuse_as_table_set(proc(PredId, ProcId),
|
|
reuse_as_and_status(ReuseAs, Status), !ReuseTable).
|
|
|
|
direct_reuse_process_specific_procs(SharingTable, PPIds,
|
|
!ModuleInfo, !ReuseTable) :-
|
|
list.foldl2(direct_reuse_process_ppid(SharingTable), PPIds,
|
|
!ModuleInfo, !ReuseTable).
|
|
|
|
:- pred direct_reuse_process_ppid(sharing_as_table::in, pred_proc_id::in,
|
|
module_info::in, module_info::out,
|
|
reuse_as_table::in, reuse_as_table::out) is det.
|
|
|
|
direct_reuse_process_ppid(SharingTable, proc(PredId, ProcId),
|
|
!ModuleInfo, !ReuseTable) :-
|
|
direct_reuse_process_proc(SharingTable, PredId, ProcId,
|
|
!ModuleInfo, !ReuseTable).
|
|
|
|
% Process one individual procedure.
|
|
%
|
|
:- pred direct_reuse_process_proc(sharing_as_table::in,
|
|
pred_id::in, proc_id::in, module_info::in, module_info::out,
|
|
reuse_as_table::in, reuse_as_table::out) is det.
|
|
|
|
direct_reuse_process_proc(SharingTable, PredId, ProcId,
|
|
!ModuleInfo, !ReuseTable) :-
|
|
module_info_get_preds(!.ModuleInfo, Preds0),
|
|
map.lookup(Preds0, PredId, Pred0),
|
|
pred_info_get_procedures(Pred0, Procs0),
|
|
map.lookup(Procs0, ProcId, Proc0),
|
|
|
|
direct_reuse_process_proc_2(SharingTable, PredId, ProcId,
|
|
!.ModuleInfo, Pred0, Proc0, Proc, ReuseAs),
|
|
% XXX is this right?
|
|
Status = optimal,
|
|
AsAndStatus = reuse_as_and_status(ReuseAs, Status),
|
|
reuse_as_table_set(proc(PredId, ProcId), AsAndStatus, !ReuseTable),
|
|
|
|
map.det_update(Procs0, ProcId, Proc, Procs),
|
|
pred_info_set_procedures(Procs, Pred0, Pred),
|
|
map.det_update(Preds0, PredId, Pred, Preds),
|
|
module_info_set_preds(Preds, !ModuleInfo).
|
|
|
|
:- pred direct_reuse_process_proc_2(sharing_as_table::in,
|
|
pred_id::in, proc_id::in, module_info::in,
|
|
pred_info::in, proc_info::in, proc_info::out, reuse_as::out) is det.
|
|
|
|
direct_reuse_process_proc_2(SharingTable, PredId, ProcId,
|
|
ModuleInfo, PredInfo, !ProcInfo, ReuseAs) :-
|
|
module_info_get_globals(ModuleInfo, Globals),
|
|
globals.lookup_bool_option(Globals, very_verbose, VeryVerbose),
|
|
|
|
trace [io(!IO)] (
|
|
write_proc_progress_message("% Direct reuse analysis of ",
|
|
PredId, ProcId, ModuleInfo, !IO)
|
|
),
|
|
|
|
proc_info_get_goal(!.ProcInfo, Goal0),
|
|
|
|
% Determine the deconstructions in which data may potentially become
|
|
% garbage.
|
|
|
|
determine_dead_deconstructions(ModuleInfo, PredInfo, !.ProcInfo,
|
|
SharingTable, Goal0, DeadCellTable),
|
|
trace [io(!IO)] (
|
|
dead_cell_table_maybe_dump(VeryVerbose, DeadCellTable, !IO)
|
|
),
|
|
|
|
% Determine how the detected dead datastructures can be reused.
|
|
% This annotates the goal with potential reuses.
|
|
|
|
determine_reuse(ModuleInfo, !.ProcInfo, DeadCellTable, Goal0, Goal,
|
|
ReuseAs),
|
|
|
|
proc_info_set_goal(Goal, !ProcInfo),
|
|
|
|
trace [io(!IO)] (
|
|
maybe_write_string(VeryVerbose, "% reuse analysis done.\n", !IO)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% We use the type dead_cell_table to collect all deconstructions that possibly
|
|
% leave garbage behind.
|
|
%
|
|
|
|
% A dead_cell_table maps program points onto reuse conditions.
|
|
%
|
|
:- type dead_cell_table == map(program_point, reuse_condition).
|
|
|
|
% Initialise a dead_cell_table.
|
|
%
|
|
:- func dead_cell_table_init = dead_cell_table.
|
|
|
|
dead_cell_table_init = map.init.
|
|
|
|
% Check whether the table is empty.
|
|
%
|
|
:- pred dead_cell_table_is_empty(dead_cell_table::in) is semidet.
|
|
|
|
dead_cell_table_is_empty(Table) :-
|
|
map.is_empty(Table).
|
|
|
|
% Succeeds if the given program point is listed in the table. Return
|
|
% the associated reuse_condition.
|
|
%
|
|
:- func dead_cell_table_search(program_point, dead_cell_table)
|
|
= reuse_condition is semidet.
|
|
|
|
dead_cell_table_search(PP, Table) = ReuseCond :-
|
|
map.search(Table, PP, ReuseCond).
|
|
|
|
% Add a program point and its associated reuse_condition to the table.
|
|
%
|
|
:- pred dead_cell_table_set(program_point::in, reuse_condition::in,
|
|
dead_cell_table::in, dead_cell_table::out) is det.
|
|
|
|
dead_cell_table_set(PP, RC, !Table) :-
|
|
svmap.set(PP, RC, !Table).
|
|
|
|
% Remove a program point from the table.
|
|
%
|
|
:- pred dead_cell_table_remove(program_point::in,
|
|
dead_cell_table::in, dead_cell_table::out) is det.
|
|
|
|
dead_cell_table_remove(PP, !Table) :-
|
|
svmap.det_remove(PP, _, !Table).
|
|
|
|
% Remove all program points from the table for which the reuse_conditions
|
|
% are "conditional".
|
|
%
|
|
:- pred dead_cell_table_remove_conditionals(dead_cell_table::in,
|
|
dead_cell_table::out) is det.
|
|
|
|
dead_cell_table_remove_conditionals(!Table) :-
|
|
map.foldl(dead_cell_table_add_unconditional, !.Table,
|
|
dead_cell_table_init, !:Table).
|
|
|
|
:- pred dead_cell_table_add_unconditional(program_point::in,
|
|
reuse_condition::in, dead_cell_table::in, dead_cell_table::out) is det.
|
|
|
|
dead_cell_table_add_unconditional(PP, C, !Table) :-
|
|
( reuse_condition_is_conditional(C) ->
|
|
true
|
|
;
|
|
dead_cell_table_set(PP, C, !Table)
|
|
).
|
|
|
|
% Dump the contents of the table.
|
|
%
|
|
:- pred dead_cell_table_maybe_dump(bool::in, dead_cell_table::in,
|
|
io::di, io::uo) is det.
|
|
|
|
dead_cell_table_maybe_dump(MaybeDump, Table, !IO) :-
|
|
(
|
|
MaybeDump = no
|
|
;
|
|
MaybeDump = yes,
|
|
io.write_string("\t\t|--------|\n", !IO),
|
|
map.foldl(dead_cell_entry_dump, Table, !IO),
|
|
io.write_string("\t\t|--------|\n", !IO)
|
|
).
|
|
|
|
:- pred dead_cell_entry_dump(program_point::in, reuse_condition::in,
|
|
io::di, io::uo) is det.
|
|
|
|
dead_cell_entry_dump(PP, Cond, !IO) :-
|
|
( reuse_condition_is_conditional(Cond) ->
|
|
io.write_string("\t\t| cond |\t", !IO)
|
|
;
|
|
io.write_string("\t\t| always |\t", !IO)
|
|
),
|
|
dump_program_point(PP, !IO),
|
|
io.write_string("\n", !IO).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- func this_file = string.
|
|
|
|
this_file = "structure_sharing.direct.m".
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module transform_hlds.ctgc.structure_reuse.direct.
|
|
%-----------------------------------------------------------------------------%
|