mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-14 21:35:49 +00:00
Estimated hours taken: 12
The main changes are
1 associating a name with the arguments of constructors
2 removing the follow_vars field from calls, higher-order calls
and complicated unifications, since they are not used
3 merging the follow_vars and store_alloc passes, since they logically
belong together
4 add a new module, lco, for detecting opportunities for last
call optimization modulo constructor application; it won't
actually apply the optimization until the mode system becomes
expressive enough to handle it (this module detects 529 opportunities
in the compiler and library)
5 make "-O3 --optimize-value-number" do the right thing; previously,
it used not to apply value numbering because the vnrepeat option
defaulted to zero
6 don't refer to .err2 files anymore; use .err instead.
prog_data:
The list associated with each value of type "constructor" now
contains not only the types of the arguments but their names as well.
equiv_type, hlds_data, hlds_out, make_hlds, mercury_to_{goedel,mercury},
mode_util, module_qual, shapes, type_util, unify_proc:
Modify the traversal of type definitions to account for the names
in the lists inside values of type "constructor".
prog_io:
Parse argument names. An unrelated change is that we now
check whether :- pred declarations give modes to some of their
arguments but not to all, in which case we return an error.
hlds_goal:
Remove the follow_vars field from calls, higher-order calls
and complicated unifications.
*.m:
Handle the new arities of calls, higher order calls and complicated
unifications.
mercury_compile:
Don't call follow_vars directly anymore, but do call lco if its option
is set. Also flush the main output before a call to maybe_report_stats
to prevent ugly output.
store_alloc:
Call follow_vars directly.
follow_vars:
Expose the initialization and traversal predicates for store_alloc.
lco:
Find opportunities for last call optimization modulo constructor
application.
passes_aux:
Add a HLDS traversal type for lco.
optimize:
Consider the vnrepeat count to be zero unless value numbering is on.
options:
Set the default value of vnrepeat to 1.
modules:
Don't refer to .err2 files.
294 lines
8.2 KiB
Mathematica
294 lines
8.2 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1995 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.
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% optimize.m - LLDS to LLDS optimizations.
|
|
|
|
% Main author: zs.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module optimize.
|
|
|
|
:- interface.
|
|
|
|
:- import_module llds, io, options.
|
|
|
|
:- pred optimize__main(list(c_procedure), list(c_procedure),
|
|
io__state, io__state).
|
|
:- mode optimize__main(in, out, di, uo) is det.
|
|
|
|
:- pred optimize__proc(c_procedure, c_procedure, io__state, io__state).
|
|
:- mode optimize__proc(in, out, di, uo) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module bool, list, map, bimap, int, std_util.
|
|
|
|
:- import_module jumpopt, labelopt, dupelim, frameopt, peephole, value_number.
|
|
:- import_module globals, passes_aux, opt_util, opt_debug, vn_debug.
|
|
|
|
optimize__main([], []) --> [].
|
|
optimize__main([Proc0|Procs0], [Proc|Procs]) -->
|
|
optimize__proc(Proc0, Proc),
|
|
optimize__main(Procs0, Procs).
|
|
|
|
optimize__proc(c_procedure(Name, Arity, Mode, Instrs0),
|
|
c_procedure(Name, Arity, Mode, Instrs)) -->
|
|
globals__io_lookup_bool_option(debug_opt, DebugOpt),
|
|
opt_debug__msg(DebugOpt, "before optimization"),
|
|
opt_debug__dump_instrs(DebugOpt, Instrs0),
|
|
globals__io_lookup_int_option(optimize_repeat, AllRepeat),
|
|
globals__io_lookup_int_option(optimize_vnrepeat, VnRepeat),
|
|
{ NovnRepeat is AllRepeat - VnRepeat },
|
|
optimize__repeat(NovnRepeat, no, Instrs0, Instrs1),
|
|
globals__io_lookup_bool_option(optimize_value_number, ValueNumber),
|
|
( { ValueNumber = yes } ->
|
|
optimize__repeat(VnRepeat, yes, Instrs1, Instrs2)
|
|
;
|
|
{ Instrs2 = Instrs1 }
|
|
),
|
|
optimize__nonrepeat(Instrs2, Instrs).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred optimize__repeat(int, bool, list(instruction), list(instruction),
|
|
io__state, io__state).
|
|
:- mode optimize__repeat(in, in, in, out, di, uo) is det.
|
|
|
|
optimize__repeat(Iter0, DoVn, Instrs0, Instrs) -->
|
|
(
|
|
{ Iter0 > 0 }
|
|
->
|
|
{ bimap__init(TeardownMap) },
|
|
optimize__repeated(Instrs0, DoVn, no, TeardownMap,
|
|
Instrs1, Mod),
|
|
( { Mod = yes } ->
|
|
{ Iter1 is Iter0 - 1 },
|
|
optimize__repeat(Iter1, DoVn, Instrs1, Instrs)
|
|
;
|
|
{ Instrs = Instrs1 }
|
|
)
|
|
;
|
|
{ Instrs = Instrs0 }
|
|
).
|
|
|
|
% We short-circuit jump sequences before normal peepholing
|
|
% to create more opportunities for use of the tailcall macro.
|
|
|
|
:- pred optimize__repeated(list(instruction), bool, bool,
|
|
bimap(label, label), list(instruction), bool, io__state, io__state).
|
|
:- mode optimize__repeated(in, in, in, in, out, out, di, uo) is det.
|
|
|
|
optimize__repeated(Instrs0, DoVn, Final, TeardownMap, Instrs, Mod) -->
|
|
globals__io_lookup_bool_option(very_verbose, VeryVerbose),
|
|
globals__io_lookup_bool_option(debug_opt, DebugOpt),
|
|
{ opt_util__find_first_label(Instrs0, Label) },
|
|
{ opt_util__format_label(Label, LabelStr) },
|
|
|
|
globals__io_lookup_bool_option(optimize_value_number, ValueNumber),
|
|
( { ValueNumber = yes, DoVn = yes } ->
|
|
( { VeryVerbose = yes } ->
|
|
io__write_string("% Optimizing value number for "),
|
|
io__write_string(LabelStr),
|
|
io__write_string("\n")
|
|
;
|
|
[]
|
|
),
|
|
value_number__main(Instrs0, Instrs1),
|
|
( { Instrs1 = Instrs0 } ->
|
|
[]
|
|
;
|
|
opt_debug__msg(DebugOpt, "after value numbering"),
|
|
opt_debug__dump_instrs(DebugOpt, Instrs1)
|
|
)
|
|
;
|
|
{ Instrs1 = Instrs0 }
|
|
),
|
|
globals__io_lookup_bool_option(optimize_jumps, Jumpopt),
|
|
globals__io_lookup_bool_option(optimize_fulljumps, FullJumpopt),
|
|
( { Jumpopt = yes } ->
|
|
( { VeryVerbose = yes } ->
|
|
io__write_string("% Optimizing jumps for "),
|
|
io__write_string(LabelStr),
|
|
io__write_string("\n")
|
|
;
|
|
[]
|
|
),
|
|
{ jumpopt__main(Instrs1, FullJumpopt, Final, Instrs2, Mod1) },
|
|
( { Instrs2 = Instrs1 } ->
|
|
[]
|
|
;
|
|
opt_debug__msg(DebugOpt, "after jump optimization"),
|
|
opt_debug__dump_instrs(DebugOpt, Instrs2)
|
|
)
|
|
;
|
|
{ Instrs2 = Instrs1 },
|
|
{ Mod1 = no }
|
|
),
|
|
globals__io_lookup_bool_option(optimize_peep, Peephole),
|
|
( { Peephole = yes } ->
|
|
( { VeryVerbose = yes } ->
|
|
io__write_string("% Optimizing locally for "),
|
|
io__write_string(LabelStr),
|
|
io__write_string("\n")
|
|
;
|
|
[]
|
|
),
|
|
{ peephole__optimize(Instrs2, Instrs3, TeardownMap, Final,
|
|
Mod2) },
|
|
( { Instrs3 = Instrs2 } ->
|
|
[]
|
|
;
|
|
opt_debug__msg(DebugOpt, "after peepholing"),
|
|
opt_debug__dump_instrs(DebugOpt, Instrs3)
|
|
)
|
|
;
|
|
{ Instrs3 = Instrs2 },
|
|
{ Mod2 = no }
|
|
),
|
|
globals__io_lookup_bool_option(optimize_labels, LabelElim),
|
|
( { LabelElim = yes } ->
|
|
( { VeryVerbose = yes } ->
|
|
io__write_string("% Optimizing labels for "),
|
|
io__write_string(LabelStr),
|
|
io__write_string("\n")
|
|
;
|
|
[]
|
|
),
|
|
{ labelopt__main(Instrs3, Final, Instrs4, Mod3) },
|
|
( { Instrs4 = Instrs3 } ->
|
|
[]
|
|
;
|
|
opt_debug__msg(DebugOpt, "after label optimization"),
|
|
opt_debug__dump_instrs(DebugOpt, Instrs4)
|
|
)
|
|
;
|
|
{ Instrs4 = Instrs3 },
|
|
{ Mod3 = no }
|
|
),
|
|
globals__io_lookup_bool_option(optimize_dups, DupElim),
|
|
( { DupElim = yes } ->
|
|
( { VeryVerbose = yes } ->
|
|
io__write_string("% Optimizing duplicates for "),
|
|
io__write_string(LabelStr),
|
|
io__write_string("\n")
|
|
;
|
|
[]
|
|
),
|
|
{ dupelim__main(Instrs4, Instrs) },
|
|
( { Instrs = Instrs4 } ->
|
|
[]
|
|
;
|
|
opt_debug__msg(DebugOpt, "after duplicate elimination"),
|
|
opt_debug__dump_instrs(DebugOpt, Instrs)
|
|
)
|
|
;
|
|
{ Instrs = Instrs4 }
|
|
),
|
|
{ Mod1 = no, Mod2 = no, Mod3 = no, Instrs = Instrs0 ->
|
|
Mod = no
|
|
;
|
|
Mod = yes
|
|
},
|
|
globals__io_lookup_bool_option(statistics, Statistics),
|
|
maybe_report_stats(Statistics).
|
|
|
|
:- pred optimize__nonrepeat(list(instruction), list(instruction),
|
|
io__state, io__state).
|
|
:- mode optimize__nonrepeat(in, out, di, uo) is det.
|
|
|
|
optimize__nonrepeat(Instrs0, Instrs) -->
|
|
globals__io_lookup_bool_option(very_verbose, VeryVerbose),
|
|
globals__io_lookup_bool_option(debug_opt, DebugOpt),
|
|
{ opt_util__find_first_label(Instrs0, Label) },
|
|
{ opt_util__format_label(Label, LabelStr) },
|
|
|
|
globals__io_lookup_bool_option(optimize_frames, FrameOpt),
|
|
( { FrameOpt = yes } ->
|
|
( { VeryVerbose = yes } ->
|
|
io__write_string("% Optimizing frames for "),
|
|
io__write_string(LabelStr),
|
|
io__write_string("\n")
|
|
;
|
|
[]
|
|
),
|
|
globals__io_lookup_bool_option(optimize_delay_slot, DelaySlot),
|
|
{ frameopt__main(Instrs0, Instrs1, DelaySlot, TeardownMap, _) },
|
|
( { Instrs1 = Instrs0 } ->
|
|
[]
|
|
;
|
|
opt_debug__msg(DebugOpt, "after frame optimization"),
|
|
opt_debug__dump_instrs(DebugOpt, Instrs1)
|
|
)
|
|
;
|
|
{ Instrs1 = Instrs0 },
|
|
{ bimap__init(TeardownMap) }
|
|
),
|
|
globals__io_lookup_bool_option(optimize_peep, Peephole),
|
|
( { FrameOpt = yes, Peephole = yes } ->
|
|
% get rid of useless incr_sp/decr_sp pairs
|
|
{ peephole__optimize(Instrs1, Instrs2, TeardownMap, yes, _) },
|
|
( { Instrs2 = Instrs1 } ->
|
|
[]
|
|
;
|
|
opt_debug__msg(DebugOpt, "after peepholing"),
|
|
opt_debug__dump_instrs(DebugOpt, Instrs2)
|
|
)
|
|
;
|
|
{ Instrs2 = Instrs1 }
|
|
),
|
|
globals__io_lookup_bool_option(optimize_value_number, ValueNumber),
|
|
( { ValueNumber = yes } ->
|
|
( { VeryVerbose = yes } ->
|
|
io__write_string("% Optimizing post value number for "),
|
|
io__write_string(LabelStr),
|
|
io__write_string("\n")
|
|
;
|
|
[]
|
|
),
|
|
{ value_number__post_main(Instrs2, Instrs3) },
|
|
( { Instrs3 = Instrs2 } ->
|
|
[]
|
|
;
|
|
opt_debug__msg(DebugOpt, "after post value number"),
|
|
opt_debug__dump_instrs(DebugOpt, Instrs3)
|
|
)
|
|
;
|
|
{ Instrs3 = Instrs2 }
|
|
),
|
|
( { FrameOpt = yes ; ValueNumber = yes } ->
|
|
optimize__repeated(Instrs3, no, yes, TeardownMap,
|
|
Instrs4, RepMod),
|
|
( { RepMod = yes, FrameOpt = yes, Peephole = yes } ->
|
|
{ bimap__init(Empty2) },
|
|
{ peephole__optimize(Instrs4, Instrs5, Empty2, yes,
|
|
_) },
|
|
( { Instrs5 = Instrs4 } ->
|
|
[]
|
|
;
|
|
opt_debug__msg(DebugOpt, "after peepholing"),
|
|
opt_debug__dump_instrs(DebugOpt, Instrs5)
|
|
)
|
|
;
|
|
{ Instrs5 = Instrs4 }
|
|
),
|
|
( { frameopt__is_succip_restored(Instrs4) } ->
|
|
{ Instrs = Instrs5 }
|
|
;
|
|
{ frameopt__dont_save_succip(Instrs5, Instrs) },
|
|
( { Instrs = Instrs5 } ->
|
|
[]
|
|
;
|
|
opt_debug__msg(DebugOpt, "after unsave succip"),
|
|
opt_debug__dump_instrs(DebugOpt, Instrs)
|
|
)
|
|
)
|
|
;
|
|
{ Instrs = Instrs3 }
|
|
).
|