mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-05-01 01:04:43 +00:00
Estimated hours taken: 30+
arg_info:
Fix allocation to work properly for --args compact.
bytecode*:
Handle complex deconstruction unifications. Not really tested because
I can't find a test case.
bytecode_gen, call_gen, code_util:
Use the new method to handle builtin predicates/functions. We now
handle reverse mode arithmetic and unary plus/minus as builtins.
code_gen, code_init, follow_vars, hlds_pred:
Put back the initial follow_vars field of the proc_info, since this
may allow the code generator to emit better code at the starts of
of predicates.
inlining:
Don't inline recursive predicates.
goals_util:
Add a predicate to find out if a goal calls a particular predicate.
Used in inlining to find out if a predicate is recursive.
unused_args:
Remove code that used to set the mode of unused args to free->free.
Since this changes the arg from top_in to top_unused *without* code
in other modules being aware of the change, this screws up --args
compact.
llds, llds_out, garbage_out:
Prepare for the move to the new type_info structure by adding a new
"module" type for defining structures holding type_infos. Not
currently generated or output.
llds, opt_debug, opt_util, vn_type, vn_cost, vn_temploc:
Change the argument of temp to be a reg, not an int, allowing
floating point temporaries.
vn_type:
Add information about the number of floating point registers and
temporaries to the parameter structure (these are currently unused).
llds, dupelim, frameopt, livemap, middle_rec, value_number, vn_filter,
vn_verify:
Add an extra field to blocks giving the number of float temporaries.
options:
Add parameters to configure the number of floating point registers
and temporaries.
mercury_compile:
Add an extra excess assign phase at the start of the middle pass.
This should reduce the size of the code manipulated by the other
phases, and gives more accurate size information to inlining.
(The excess assign phase before code generation is I think still
needed since optimizations can introduce such assignments.)
value_number:
Optimize code sequences before and after assignments to curfr
separately, since such assignments change the meaning of framevars.
This fixes the bug that caused singleton variable warnings to contain
garbage.
vn_block, vn_flush, vn_order, vn_util:
Add special handling of assignments to curfr. This is probably
unnecessary after my change to value_number, and will be removed
again shortly :-(
vn_flush:
Improve the code generated by value numbering (1) by computing values
into the place that needs them in some special circumstances, and
(2) by fixing a bug that did not consider special registers to be
as fast as r1 etc.
vn_util:
Improve the code generated by value numbering by removing duplicates
from the list of uses of a value before trying to find out if there
is more than one use.
simplify:
Avoid overzealous optimization of main --> { ..., error(...) }.
handle_options:
Fix an error message.
code_aux:
Break an excessive long line.
329 lines
14 KiB
Mathematica
329 lines
14 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.
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% vn_filter.m - filter out redundant temp assignments
|
|
% introduced by value numbering.
|
|
|
|
% Author: zs.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module vn_filter.
|
|
|
|
:- interface.
|
|
|
|
:- import_module llds.
|
|
:- import_module list.
|
|
|
|
:- pred vn_filter__block(list(instruction), list(instruction)).
|
|
:- mode vn_filter__block(in, out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module opt_util.
|
|
:- import_module require, std_util.
|
|
|
|
vn_filter__block([], []).
|
|
vn_filter__block([Instr0 | Instrs0], Instrs) :-
|
|
(
|
|
Instr0 = Uinstr0 - _,
|
|
Uinstr0 = assign(Temp, Defn),
|
|
Temp = temp(_),
|
|
opt_util__lvals_in_rval(Defn, Deps),
|
|
vn_filter__can_substitute(Instrs0, Temp, Defn, Deps,
|
|
Instrs1)
|
|
->
|
|
vn_filter__block(Instrs1, Instrs)
|
|
;
|
|
vn_filter__block(Instrs0, Instrs1),
|
|
Instrs = [Instr0 | Instrs1]
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred vn_filter__can_substitute(list(instruction), lval, rval, list(lval),
|
|
list(instruction)).
|
|
:- mode vn_filter__can_substitute(in, in, in, in, out) is semidet.
|
|
|
|
vn_filter__can_substitute([], _, _, _, []).
|
|
vn_filter__can_substitute([Instr0 | Instrs0], Temp, Defn, Deps, Instrs) :-
|
|
Instr0 = Uinstr0 - Comment,
|
|
(
|
|
vn_filter__user_instr(Uinstr0, yes(Rval)),
|
|
opt_util__lvals_in_rval(Rval, Lvals),
|
|
list__delete_first(Lvals, Temp, OtherLvals)
|
|
->
|
|
% We don't want to perform the subsitution
|
|
% if Temp appears in the instruction more than once.
|
|
\+ list__member(Temp, OtherLvals),
|
|
\+ (
|
|
vn_filter__defining_instr(Uinstr0, yes(Lval)),
|
|
opt_util__lvals_in_lval(Lval, AccessLvals),
|
|
list__member(Temp, AccessLvals)
|
|
),
|
|
vn_filter__replace_in_user_instr(Uinstr0, Temp, Defn, Uinstr1),
|
|
Instrs = [Uinstr1 - Comment | Instrs0],
|
|
vn_filter__instrs_free_of_lval(Instrs, Temp)
|
|
;
|
|
vn_filter__defining_instr(Uinstr0, yes(Lval))
|
|
->
|
|
(
|
|
Lval = Temp
|
|
->
|
|
Instrs = [Instr0 | Instrs0]
|
|
;
|
|
list__member(Lval, Deps)
|
|
->
|
|
fail
|
|
;
|
|
opt_util__lvals_in_lval(Lval, AccessLvals),
|
|
list__delete_first(AccessLvals, Temp, OtherAccessLvals)
|
|
->
|
|
\+ list__member(Temp, OtherAccessLvals),
|
|
vn_filter__replace_in_defining_instr(Uinstr0,
|
|
Temp, Defn, Uinstr1),
|
|
Instrs = [Uinstr1 - Comment | Instrs0],
|
|
vn_filter__instrs_free_of_lval(Instrs, Temp)
|
|
;
|
|
vn_filter__can_substitute(Instrs0, Temp, Defn, Deps,
|
|
Instrs1),
|
|
Instrs = [Instr0 | Instrs1]
|
|
)
|
|
;
|
|
vn_filter__can_substitute(Instrs0, Temp, Defn, Deps, Instrs1),
|
|
Instrs = [Instr0 | Instrs1]
|
|
).
|
|
|
|
:- pred vn_filter__user_instr(instr, maybe(rval)).
|
|
:- mode vn_filter__user_instr(in, out) is det.
|
|
|
|
vn_filter__user_instr(comment(_), no).
|
|
vn_filter__user_instr(livevals(_), no).
|
|
vn_filter__user_instr(block(_, _, _), _):-
|
|
error("inappropriate instruction in vn__filter").
|
|
vn_filter__user_instr(assign(_, Rval), yes(Rval)).
|
|
vn_filter__user_instr(call(_, _, _, _), no).
|
|
vn_filter__user_instr(mkframe(_, _, _), no).
|
|
vn_filter__user_instr(modframe(_), no).
|
|
vn_filter__user_instr(label(_), no).
|
|
vn_filter__user_instr(goto(_), no).
|
|
vn_filter__user_instr(computed_goto(Rval, _), yes(Rval)).
|
|
vn_filter__user_instr(if_val(Rval, _), yes(Rval)).
|
|
vn_filter__user_instr(c_code(_), _):-
|
|
error("inappropriate instruction in vn__filter").
|
|
vn_filter__user_instr(incr_hp(_, _, Rval), yes(Rval)).
|
|
vn_filter__user_instr(mark_hp(_), no).
|
|
vn_filter__user_instr(restore_hp(Rval), yes(Rval)).
|
|
vn_filter__user_instr(store_ticket(_), no).
|
|
vn_filter__user_instr(restore_ticket(Rval), yes(Rval)).
|
|
vn_filter__user_instr(discard_ticket, no).
|
|
vn_filter__user_instr(incr_sp(_), no).
|
|
vn_filter__user_instr(decr_sp(_), no).
|
|
vn_filter__user_instr(pragma_c(_, _, _, _), _):-
|
|
error("inappropriate instruction in vn__filter").
|
|
|
|
:- pred vn_filter__replace_in_user_instr(instr, lval, rval, instr).
|
|
:- mode vn_filter__replace_in_user_instr(in, in, in, out) is det.
|
|
|
|
vn_filter__replace_in_user_instr(comment(_), _, _, _) :-
|
|
error("non-user instruction in vn_filter__replace_in_user_instr").
|
|
vn_filter__replace_in_user_instr(livevals(_), _, _, _) :-
|
|
error("non-user instruction in vn_filter__replace_in_user_instr").
|
|
vn_filter__replace_in_user_instr(block(_, _, _), _, _, _):-
|
|
error("inappropriate instruction in vn__filter").
|
|
vn_filter__replace_in_user_instr(assign(Lval, Rval0), Temp, Defn,
|
|
assign(Lval, Rval)) :-
|
|
vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
|
|
vn_filter__replace_in_user_instr(call(_, _, _, _), _, _, _) :-
|
|
error("non-user instruction in vn_filter__replace_in_user_instr").
|
|
vn_filter__replace_in_user_instr(mkframe(_, _, _), _, _, _) :-
|
|
error("non-user instruction in vn_filter__replace_in_user_instr").
|
|
vn_filter__replace_in_user_instr(modframe(_), _, _, _) :-
|
|
error("non-user instruction in vn_filter__replace_in_user_instr").
|
|
vn_filter__replace_in_user_instr(label(_), _, _, _) :-
|
|
error("non-user instruction in vn_filter__replace_in_user_instr").
|
|
vn_filter__replace_in_user_instr(goto(_), _, _, _) :-
|
|
error("non-user instruction in vn_filter__replace_in_user_instr").
|
|
vn_filter__replace_in_user_instr(computed_goto(Rval0, Labels), Temp, Defn,
|
|
computed_goto(Rval, Labels)) :-
|
|
vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
|
|
vn_filter__replace_in_user_instr(if_val(Rval0, Label), Temp, Defn,
|
|
if_val(Rval, Label)) :-
|
|
vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
|
|
vn_filter__replace_in_user_instr(c_code(_), _, _, _):-
|
|
error("inappropriate instruction in vn__filter").
|
|
vn_filter__replace_in_user_instr(incr_hp(Lval, Tag, Rval0), Temp, Defn,
|
|
incr_hp(Lval, Tag, Rval)) :-
|
|
vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
|
|
vn_filter__replace_in_user_instr(mark_hp(_), _, _, _) :-
|
|
error("non-user instruction in vn_filter__replace_in_user_instr").
|
|
vn_filter__replace_in_user_instr(restore_hp(Rval0), Temp, Defn,
|
|
restore_hp(Rval)) :-
|
|
vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
|
|
vn_filter__replace_in_user_instr(store_ticket(_), _, _, _) :-
|
|
error("non-user instruction in vn_filter__replace_in_user_instr").
|
|
vn_filter__replace_in_user_instr(restore_ticket(Rval0), Temp, Defn,
|
|
restore_ticket(Rval)) :-
|
|
vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
|
|
vn_filter__replace_in_user_instr(discard_ticket, _, _, _) :-
|
|
error("non-user instruction in vn_filter__replace_in_user_instr").
|
|
vn_filter__replace_in_user_instr(incr_sp(_), _, _, _) :-
|
|
error("non-user instruction in vn_filter__replace_in_user_instr").
|
|
vn_filter__replace_in_user_instr(decr_sp(_), _, _, _) :-
|
|
error("non-user instruction in vn_filter__replace_in_user_instr").
|
|
vn_filter__replace_in_user_instr(pragma_c(_, _, _, _), _, _, _):-
|
|
error("inappropriate instruction in vn__filter").
|
|
|
|
:- pred vn_filter__defining_instr(instr, maybe(lval)).
|
|
:- mode vn_filter__defining_instr(in, out) is det.
|
|
|
|
vn_filter__defining_instr(comment(_), no).
|
|
vn_filter__defining_instr(livevals(_), no).
|
|
vn_filter__defining_instr(block(_, _, _), _):-
|
|
error("inappropriate instruction in vn__filter").
|
|
vn_filter__defining_instr(assign(Lval, _), yes(Lval)).
|
|
vn_filter__defining_instr(call(_, _, _, _), no).
|
|
vn_filter__defining_instr(mkframe(_, _, _), no).
|
|
vn_filter__defining_instr(modframe(_), no).
|
|
vn_filter__defining_instr(label(_), no).
|
|
vn_filter__defining_instr(goto(_), no).
|
|
vn_filter__defining_instr(computed_goto(_, _), no).
|
|
vn_filter__defining_instr(if_val(_, _), no).
|
|
vn_filter__defining_instr(c_code(_), _):-
|
|
error("inappropriate instruction in vn__filter").
|
|
vn_filter__defining_instr(incr_hp(Lval, _, _), yes(Lval)).
|
|
vn_filter__defining_instr(mark_hp(Lval), yes(Lval)).
|
|
vn_filter__defining_instr(restore_hp(_), no).
|
|
vn_filter__defining_instr(store_ticket(Lval), yes(Lval)).
|
|
vn_filter__defining_instr(restore_ticket(_), no).
|
|
vn_filter__defining_instr(discard_ticket, no).
|
|
vn_filter__defining_instr(incr_sp(_), no).
|
|
vn_filter__defining_instr(decr_sp(_), no).
|
|
vn_filter__defining_instr(pragma_c(_, _, _, _), _):-
|
|
error("inappropriate instruction in vn__filter").
|
|
|
|
:- pred vn_filter__replace_in_defining_instr(instr, lval, rval, instr).
|
|
:- mode vn_filter__replace_in_defining_instr(in, in, in, out) is det.
|
|
|
|
vn_filter__replace_in_defining_instr(comment(_), _, _, _) :-
|
|
error("non-def instruction in vn_filter__replace_in_defining_instr").
|
|
vn_filter__replace_in_defining_instr(livevals(_), _, _, _) :-
|
|
error("non-def instruction in vn_filter__replace_in_defining_instr").
|
|
vn_filter__replace_in_defining_instr(block(_, _, _), _, _, _):-
|
|
error("inappropriate instruction in vn__filter").
|
|
vn_filter__replace_in_defining_instr(assign(Lval0, Rval), Temp, Defn,
|
|
assign(Lval, Rval)) :-
|
|
vn_filter__replace_in_lval(Lval0, Temp, Defn, Lval).
|
|
vn_filter__replace_in_defining_instr(call(_, _, _, _), _, _, _) :-
|
|
error("non-def instruction in vn_filter__replace_in_defining_instr").
|
|
vn_filter__replace_in_defining_instr(mkframe(_, _, _), _, _, _) :-
|
|
error("non-def instruction in vn_filter__replace_in_defining_instr").
|
|
vn_filter__replace_in_defining_instr(modframe(_), _, _, _) :-
|
|
error("non-def instruction in vn_filter__replace_in_defining_instr").
|
|
vn_filter__replace_in_defining_instr(label(_), _, _, _) :-
|
|
error("non-def instruction in vn_filter__replace_in_defining_instr").
|
|
vn_filter__replace_in_defining_instr(goto(_), _, _, _) :-
|
|
error("non-def instruction in vn_filter__replace_in_defining_instr").
|
|
vn_filter__replace_in_defining_instr(computed_goto(_, _), _, _, _) :-
|
|
error("non-def instruction in vn_filter__replace_in_defining_instr").
|
|
vn_filter__replace_in_defining_instr(if_val(_, _), _, _, _) :-
|
|
error("non-def instruction in vn_filter__replace_in_defining_instr").
|
|
vn_filter__replace_in_defining_instr(c_code(_), _, _, _):-
|
|
error("inappropriate instruction in vn__filter").
|
|
vn_filter__replace_in_defining_instr(incr_hp(Lval0, Tag, Rval), Temp, Defn,
|
|
incr_hp(Lval, Tag, Rval)) :-
|
|
vn_filter__replace_in_lval(Lval0, Temp, Defn, Lval).
|
|
vn_filter__replace_in_defining_instr(mark_hp(Lval0), Temp, Defn,
|
|
mark_hp(Lval)) :-
|
|
vn_filter__replace_in_lval(Lval0, Temp, Defn, Lval).
|
|
vn_filter__replace_in_defining_instr(restore_hp(_), _, _, _) :-
|
|
error("non-def instruction in vn_filter__replace_in_defining_instr").
|
|
vn_filter__replace_in_defining_instr(store_ticket(Lval0), Temp, Defn,
|
|
store_ticket(Lval)) :-
|
|
vn_filter__replace_in_lval(Lval0, Temp, Defn, Lval).
|
|
vn_filter__replace_in_defining_instr(restore_ticket(_), _, _, _) :-
|
|
error("non-def instruction in vn_filter__replace_in_defining_instr").
|
|
vn_filter__replace_in_defining_instr(discard_ticket, _, _, _) :-
|
|
error("non-def instruction in vn_filter__replace_in_defining_instr").
|
|
vn_filter__replace_in_defining_instr(incr_sp(_), _, _, _) :-
|
|
error("non-def instruction in vn_filter__replace_in_defining_instr").
|
|
vn_filter__replace_in_defining_instr(decr_sp(_), _, _, _) :-
|
|
error("non-def instruction in vn_filter__replace_in_defining_instr").
|
|
vn_filter__replace_in_defining_instr(pragma_c(_, _, _, _), _, _, _):-
|
|
error("inappropriate instruction in vn__filter").
|
|
|
|
:- pred vn_filter__replace_in_lval(lval, lval, rval, lval).
|
|
:- mode vn_filter__replace_in_lval(in, in, in, out) is det.
|
|
|
|
vn_filter__replace_in_lval(reg(R), _, _, reg(R)).
|
|
vn_filter__replace_in_lval(stackvar(N), _, _, stackvar(N)).
|
|
vn_filter__replace_in_lval(framevar(N), _, _, framevar(N)).
|
|
vn_filter__replace_in_lval(succip, _, _, succip).
|
|
vn_filter__replace_in_lval(maxfr, _, _, maxfr).
|
|
vn_filter__replace_in_lval(curfr, _, _, curfr).
|
|
vn_filter__replace_in_lval(succip(Rval0), Temp, Defn, succip(Rval)) :-
|
|
vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
|
|
vn_filter__replace_in_lval(redoip(Rval0), Temp, Defn, redoip(Rval)) :-
|
|
vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
|
|
vn_filter__replace_in_lval(succfr(Rval0), Temp, Defn, succfr(Rval)) :-
|
|
vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
|
|
vn_filter__replace_in_lval(prevfr(Rval0), Temp, Defn, prevfr(Rval)) :-
|
|
vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
|
|
vn_filter__replace_in_lval(hp, _, _, hp).
|
|
vn_filter__replace_in_lval(sp, _, _, sp).
|
|
vn_filter__replace_in_lval(field(Tag, Rval1, Rval2), Temp, Defn,
|
|
field(Tag, Rval3, Rval4)) :-
|
|
vn_filter__replace_in_rval(Rval1, Temp, Defn, Rval3),
|
|
vn_filter__replace_in_rval(Rval2, Temp, Defn, Rval4).
|
|
vn_filter__replace_in_lval(lvar(_), _, _, _) :-
|
|
error("found lvar in vn_filter__replace_in_lval").
|
|
vn_filter__replace_in_lval(temp(N), _, _, temp(N)).
|
|
|
|
:- pred vn_filter__replace_in_rval(rval, lval, rval, rval).
|
|
:- mode vn_filter__replace_in_rval(in, in, in, out) is det.
|
|
|
|
vn_filter__replace_in_rval(lval(Lval0), Temp, Defn, Rval) :-
|
|
( Lval0 = Temp ->
|
|
Rval = Defn
|
|
;
|
|
vn_filter__replace_in_lval(Lval0, Temp, Defn, Lval),
|
|
Rval = lval(Lval)
|
|
).
|
|
vn_filter__replace_in_rval(var(_), _, _, _) :-
|
|
error("found var in vn_filter__replace_in_rval").
|
|
vn_filter__replace_in_rval(create(Tag, Args, Label), _, _,
|
|
create(Tag, Args, Label)).
|
|
vn_filter__replace_in_rval(mkword(Tag, Rval0), Temp, Defn, mkword(Tag, Rval)) :-
|
|
vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
|
|
vn_filter__replace_in_rval(const(Const), _, _, const(Const)).
|
|
vn_filter__replace_in_rval(unop(Unop, Rval0), Temp, Defn, unop(Unop, Rval)) :-
|
|
vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
|
|
vn_filter__replace_in_rval(binop(Binop, Rval1, Rval2), Temp, Defn,
|
|
binop(Binop, Rval3, Rval4)) :-
|
|
vn_filter__replace_in_rval(Rval1, Temp, Defn, Rval3),
|
|
vn_filter__replace_in_rval(Rval2, Temp, Defn, Rval4).
|
|
|
|
:- pred vn_filter__instrs_free_of_lval(list(instruction), lval).
|
|
:- mode vn_filter__instrs_free_of_lval(in, in) is semidet.
|
|
|
|
vn_filter__instrs_free_of_lval([], _).
|
|
vn_filter__instrs_free_of_lval([Uinstr - _ | Instrs], Temp) :-
|
|
( vn_filter__user_instr(Uinstr, yes(Rval)) ->
|
|
opt_util__rval_free_of_lval(Rval, Temp)
|
|
;
|
|
true
|
|
),
|
|
( vn_filter__defining_instr(Uinstr, yes(Lval)) ->
|
|
Lval \= Temp,
|
|
opt_util__lval_access_rvals(Lval, Rvals),
|
|
opt_util__rvals_free_of_lval(Rvals, Temp)
|
|
;
|
|
true
|
|
),
|
|
vn_filter__instrs_free_of_lval(Instrs, Temp).
|