mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-20 08:19:28 +00:00
Separate procedures with newlines in .mod files.
llds.nl:
Separate procedures with newlines in .mod files.
opt_util.nl, peephole.nl:
Recognize semidet and nondet procedure epilogs. Branches to these
epilogs are replaced by the epilogs themselves.
peephole.nl:
Migrate if_val(Test, do_fail) before mkframe if possible.
value_number.nl:
It now computes livevals sets at starts of blocks and uses them
to build up a set of tables containing value number info. This
info is not yet used, but the tables are inserted into the generated
code if --peephole-value-number is used.
opt_debug{,.nu}.nl:
New files containing code to support debugging of peephole and
value_number.
Makefile.common, mercury_compile.dep:
Accommodate new files opt_debug{,.nu}.nl.
You may want to undo the changes to the compiler invocation
in Makefile.common.
This commit is contained in:
@@ -250,7 +250,7 @@ output_c_procedure_list([P|Ps]) -->
|
||||
:- mode output_c_procedure(in, di, uo) is det.
|
||||
|
||||
output_c_procedure(c_procedure(Name,Arity,Mode,Instructions)) -->
|
||||
io__write_string("/*-------------------------------------"),
|
||||
io__write_string("\n/*-------------------------------------"),
|
||||
io__write_string("------------------------------------*/\n"),
|
||||
io__write_string("/* code for predicate "),
|
||||
io__write_string(Name),
|
||||
|
||||
234
compiler/opt_debug.m
Normal file
234
compiler/opt_debug.m
Normal file
@@ -0,0 +1,234 @@
|
||||
%-----------------------------------------------------------------------------%
|
||||
|
||||
% Debugging support for LLDS to LLDS peephole optimization.
|
||||
|
||||
% Main author: zs.
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
|
||||
:- module opt_debug.
|
||||
|
||||
:- interface.
|
||||
:- import_module llds, value_number, peephole, list, std_util.
|
||||
|
||||
:- pred opt_debug__dump_tables(vn_tables, string).
|
||||
:- mode opt_debug__dump_tables(in, out) is det.
|
||||
|
||||
:- pred opt_debug__dump_lval_to_vn(assoc_list(vn_lval, vn), string).
|
||||
:- mode opt_debug__dump_lval_to_vn(in, out) is det.
|
||||
|
||||
:- pred opt_debug__dump_rval_to_vn(assoc_list(vn_rval, vn), string).
|
||||
:- mode opt_debug__dump_rval_to_vn(in, out) is det.
|
||||
|
||||
:- pred opt_debug__dump_vn_to_rval(assoc_list(vn, vn_rval), string).
|
||||
:- mode opt_debug__dump_vn_to_rval(in, out) is det.
|
||||
|
||||
:- pred opt_debug__dump_vn_to_uses(assoc_list(vn, int), string).
|
||||
:- mode opt_debug__dump_vn_to_uses(in, out) is det.
|
||||
|
||||
:- pred opt_debug__dump_vn_to_locs(assoc_list(vn, list(vn_lval)), string).
|
||||
:- mode opt_debug__dump_vn_to_locs(in, out) is det.
|
||||
|
||||
:- pred opt_debug__dump_vn(vn, string).
|
||||
:- mode opt_debug__dump_vn(in, out) is det.
|
||||
|
||||
:- pred opt_debug__dump_vn_locs(list(vn_lval), string).
|
||||
:- mode opt_debug__dump_vn_locs(in, out) is det.
|
||||
|
||||
:- pred opt_debug__dump_reg(reg, string).
|
||||
:- mode opt_debug__dump_reg(in, out) is det.
|
||||
|
||||
:- pred opt_debug__dump_vn_lval(vn_lval, string).
|
||||
:- mode opt_debug__dump_vn_lval(in, out) is det.
|
||||
|
||||
:- pred opt_debug__dump_vn_rval(vn_rval, string).
|
||||
:- mode opt_debug__dump_vn_rval(in, out) is det.
|
||||
|
||||
:- pred opt_debug__dump_const(rval_const, string).
|
||||
:- mode opt_debug__dump_const(in, out) is det.
|
||||
|
||||
:- pred opt_debug__dump_unop(unary_op, string).
|
||||
:- mode opt_debug__dump_unop(in, out) is det.
|
||||
|
||||
:- pred opt_debug__dump_binop(operator, string).
|
||||
:- mode opt_debug__dump_binop(in, out) is det.
|
||||
|
||||
:- pred opt_debug__dump_label(label, string).
|
||||
:- mode opt_debug__dump_label(in, out) is det.
|
||||
|
||||
:- pred opt_debug__print_tailmap(tailmap).
|
||||
:- mode opt_debug__print_tailmap(in) is det.
|
||||
|
||||
:- pred opt_debug__print_instmap(tailmap).
|
||||
:- mode opt_debug__print_instmap(in) is det.
|
||||
|
||||
:- pred opt_debug__print_proclist(list(pair(label, list(instruction)))).
|
||||
:- mode opt_debug__print_proclist(in) is det.
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
|
||||
:- implementation.
|
||||
:- import_module map, string.
|
||||
|
||||
opt_debug__dump_lval_to_vn([], "").
|
||||
opt_debug__dump_lval_to_vn([Vn_lval - Vn | Lval_to_vn_list], Str) :-
|
||||
opt_debug__dump_lval_to_vn(Lval_to_vn_list, Tail_str),
|
||||
opt_debug__dump_vn_lval(Vn_lval, Vn_lval_str),
|
||||
opt_debug__dump_vn(Vn, Vn_str),
|
||||
string__append_list([Vn_lval_str, " -> ", Vn_str, "\n", Tail_str], Str).
|
||||
|
||||
opt_debug__dump_tables(Vn_tables, Comment) :-
|
||||
Vn_tables = vn_tables(Next_vn,
|
||||
Lval_to_vn_table, Rval_to_vn_table,
|
||||
Vn_to_rval_table, Vn_to_uses_table,
|
||||
Vn_to_locs_table, Loc_to_vn_table),
|
||||
string__int_to_string(Next_vn, Next_vn_str),
|
||||
map__to_assoc_list(Lval_to_vn_table, Lval_to_vn_list),
|
||||
map__to_assoc_list(Rval_to_vn_table, Rval_to_vn_list),
|
||||
map__to_assoc_list(Vn_to_rval_table, Vn_to_rval_list),
|
||||
map__to_assoc_list(Vn_to_uses_table, Vn_to_uses_list),
|
||||
map__to_assoc_list(Vn_to_locs_table, Vn_to_locs_list),
|
||||
map__to_assoc_list(Loc_to_vn_table, Loc_to_vn_list),
|
||||
opt_debug__dump_lval_to_vn(Lval_to_vn_list, Lval_to_vn_str),
|
||||
opt_debug__dump_rval_to_vn(Rval_to_vn_list, Rval_to_vn_str),
|
||||
opt_debug__dump_vn_to_rval(Vn_to_rval_list, Vn_to_rval_str),
|
||||
opt_debug__dump_vn_to_uses(Vn_to_uses_list, Vn_to_uses_str),
|
||||
opt_debug__dump_vn_to_locs(Vn_to_locs_list, Vn_to_locs_str),
|
||||
opt_debug__dump_lval_to_vn( Loc_to_vn_list, Loc_to_vn_str),
|
||||
string__append_list([
|
||||
"Next vn\n", Next_vn_str,
|
||||
"\nLval to vn\n", Lval_to_vn_str,
|
||||
"\nRval to vn\n", Rval_to_vn_str,
|
||||
"\nVn to rval\n", Vn_to_rval_str,
|
||||
"\nVn to uses\n", Vn_to_uses_str,
|
||||
"\nVn to locs\n", Vn_to_locs_str,
|
||||
"\nLoc to vn\n", Loc_to_vn_str], Comment).
|
||||
|
||||
opt_debug__dump_rval_to_vn([], "").
|
||||
opt_debug__dump_rval_to_vn([Vn_rval - Vn | Rval_to_vn_list], Str) :-
|
||||
opt_debug__dump_rval_to_vn(Rval_to_vn_list, Tail_str),
|
||||
opt_debug__dump_vn_rval(Vn_rval, Vn_rval_str),
|
||||
opt_debug__dump_vn(Vn, Vn_str),
|
||||
string__append_list([Vn_rval_str, " -> ", Vn_str, "\n", Tail_str], Str).
|
||||
|
||||
opt_debug__dump_vn_to_rval([], "").
|
||||
opt_debug__dump_vn_to_rval([Vn - Vn_rval | Vn_to_rval_list], Str) :-
|
||||
opt_debug__dump_vn_to_rval(Vn_to_rval_list, Tail_str),
|
||||
opt_debug__dump_vn(Vn, Vn_str),
|
||||
opt_debug__dump_vn_rval(Vn_rval, Vn_rval_str),
|
||||
string__append_list([Vn_str, " -> ", Vn_rval_str, "\n", Tail_str], Str).
|
||||
|
||||
opt_debug__dump_vn_to_uses([], "").
|
||||
opt_debug__dump_vn_to_uses([Vn - Uses | Vn_to_uses_list], Str) :-
|
||||
opt_debug__dump_vn_to_uses(Vn_to_uses_list, Tail_str),
|
||||
opt_debug__dump_vn(Vn, Vn_str),
|
||||
string__int_to_string(Uses, Uses_str),
|
||||
string__append_list([Vn_str, " -> ", Uses_str, "\n", Tail_str], Str).
|
||||
|
||||
opt_debug__dump_vn_to_locs([], "").
|
||||
opt_debug__dump_vn_to_locs([Vn - Vn_locs | Vn_to_locs_list], Str) :-
|
||||
opt_debug__dump_vn_to_locs(Vn_to_locs_list, Tail_str),
|
||||
opt_debug__dump_vn(Vn, Vn_str),
|
||||
opt_debug__dump_vn_locs(Vn_locs, Vn_locs_str),
|
||||
string__append_list([Vn_str, " -> ", Vn_locs_str, "\n", Tail_str], Str).
|
||||
|
||||
opt_debug__dump_vn(Vn, Str) :-
|
||||
string__int_to_string(Vn, Str).
|
||||
|
||||
opt_debug__dump_vn_locs([], "").
|
||||
opt_debug__dump_vn_locs([Lval | Lvals], Str) :-
|
||||
opt_debug__dump_vn_lval(Lval, Lval_str),
|
||||
opt_debug__dump_vn_locs(Lvals, Tail_str),
|
||||
string__append_list([" @", Lval_str, Tail_str], Str).
|
||||
|
||||
opt_debug__dump_reg(r(N), Str) :-
|
||||
string__int_to_string(N, N_str),
|
||||
string__append_list(["r(", N_str, ")"], Str).
|
||||
opt_debug__dump_reg(f(N), Str) :-
|
||||
string__int_to_string(N, N_str),
|
||||
string__append_list(["f(", N_str, ")"], Str).
|
||||
|
||||
opt_debug__dump_vn_lval(vn_reg(R), Str) :-
|
||||
opt_debug__dump_reg(R, R_str),
|
||||
string__append_list(["vn_reg(", R_str, ")"], Str).
|
||||
opt_debug__dump_vn_lval(vn_stackvar(N), Str) :-
|
||||
string__int_to_string(N, N_str),
|
||||
string__append_list(["vn_stackvar(", N_str, ")"], Str).
|
||||
opt_debug__dump_vn_lval(vn_framevar(N), Str) :-
|
||||
string__int_to_string(N, N_str),
|
||||
string__append_list(["vn_framevar(", N_str, ")"], Str).
|
||||
opt_debug__dump_vn_lval(vn_succip, Str) :-
|
||||
string__append_list(["vn_succip"], Str).
|
||||
opt_debug__dump_vn_lval(vn_maxfr, Str) :-
|
||||
string__append_list(["vn_maxfr"], Str).
|
||||
opt_debug__dump_vn_lval(vn_curredoip, Str) :-
|
||||
string__append_list(["vn_curredoip"], Str).
|
||||
opt_debug__dump_vn_lval(vn_hp, Str) :-
|
||||
string__append_list(["vn_hp"], Str).
|
||||
opt_debug__dump_vn_lval(vn_sp, Str) :-
|
||||
string__append_list(["vn_sp"], Str).
|
||||
opt_debug__dump_vn_lval(vn_field(T, N, F), Str) :-
|
||||
string__int_to_string(T, T_str),
|
||||
string__int_to_string(N, N_str),
|
||||
string__int_to_string(F, F_str),
|
||||
string__append_list(["vn_field(", T_str, ", ", N_str, ", ",
|
||||
F_str, ")"], Str).
|
||||
opt_debug__dump_vn_lval(vn_temp(N), Str) :-
|
||||
string__int_to_string(N, N_str),
|
||||
string__append_list(["vn_temp(", N_str, ")"], Str).
|
||||
|
||||
opt_debug__dump_vn_rval(vn_origlval(Vn_lval), Str) :-
|
||||
opt_debug__dump_vn_lval(Vn_lval, Lval_str),
|
||||
string__append_list(["vn_origlval(", Lval_str, ")"], Str).
|
||||
opt_debug__dump_vn_rval(vn_mkword(T, N), Str) :-
|
||||
string__int_to_string(T, T_str),
|
||||
string__int_to_string(N, N_str),
|
||||
string__append_list(["vn_mkword(", T_str, ", ", N_str, ")"], Str).
|
||||
opt_debug__dump_vn_rval(vn_const(C), Str) :-
|
||||
opt_debug__dump_const(C, C_str),
|
||||
string__append_list(["vn_const(", C_str, ")"], Str).
|
||||
opt_debug__dump_vn_rval(vn_field(T, N, F), Str) :-
|
||||
string__int_to_string(T, T_str),
|
||||
string__int_to_string(N, N_str),
|
||||
string__int_to_string(F, F_str),
|
||||
string__append_list(["vn_field(", T_str, ", ", N_str, ", ",
|
||||
F_str, ")"], Str).
|
||||
opt_debug__dump_vn_rval(vn_unop(O, N), Str) :-
|
||||
opt_debug__dump_unop(O, O_str),
|
||||
string__int_to_string(N, N_str),
|
||||
string__append_list(["vn_unop(", O_str, ", ", N_str, ")"], Str).
|
||||
opt_debug__dump_vn_rval(vn_binop(O, N1, N2), Str) :-
|
||||
opt_debug__dump_binop(O, O_str),
|
||||
string__int_to_string(N1, N1_str),
|
||||
string__int_to_string(N2, N2_str),
|
||||
string__append_list(["vn_binop(", O_str, ", ", N1_str, ", ",
|
||||
N2_str, ")"], Str).
|
||||
|
||||
opt_debug__dump_const(true, "true").
|
||||
opt_debug__dump_const(false, "false").
|
||||
opt_debug__dump_const(int_const(I), Str) :-
|
||||
string__int_to_string(I, Str).
|
||||
opt_debug__dump_const(string_const(I), Str) :-
|
||||
string__append_list(["\"", I, "\""], Str).
|
||||
|
||||
opt_debug__dump_unop(mktag, "mktag").
|
||||
opt_debug__dump_unop(tag, "tag").
|
||||
opt_debug__dump_unop(mkbody, "mkbody").
|
||||
opt_debug__dump_unop(body, "body").
|
||||
opt_debug__dump_unop(not, "not").
|
||||
opt_debug__dump_unop(cast_to_unsigned, "cast_to_unsigned").
|
||||
|
||||
opt_debug__dump_binop(streq, "streq").
|
||||
opt_debug__dump_binop((+), "+").
|
||||
opt_debug__dump_binop((-), "-").
|
||||
opt_debug__dump_binop((*), "*").
|
||||
opt_debug__dump_binop((/), "/").
|
||||
opt_debug__dump_binop(mod, "%").
|
||||
opt_debug__dump_binop(eq, "==").
|
||||
opt_debug__dump_binop(ne, "!=").
|
||||
opt_debug__dump_binop(and, "&&").
|
||||
opt_debug__dump_binop(or, "||").
|
||||
opt_debug__dump_binop((<), "<").
|
||||
opt_debug__dump_binop((>), ">").
|
||||
opt_debug__dump_binop((<=), "<=").
|
||||
opt_debug__dump_binop((>=), ">=").
|
||||
@@ -44,11 +44,26 @@
|
||||
:- pred opt_util__is_proceed_next(list(instruction), list(instruction)).
|
||||
:- mode opt_util__is_proceed_next(in, out) is semidet.
|
||||
|
||||
% Is a proceed instruction (i.e. a goto(succip) instruction)
|
||||
% next in the instruction list, possibly preceded by an assignment
|
||||
% to r1, a restoration of succip and a det stack frame removal?
|
||||
% If yes, return the instructions up to the proceed.
|
||||
|
||||
:- pred opt_util__is_sdproceed_next(list(instruction), list(instruction)).
|
||||
:- mode opt_util__is_sdproceed_next(in, out) is semidet.
|
||||
|
||||
% Is a succeed instruction (i.e. a goto(do_succeed) instruction)
|
||||
% next in the instruction list? If yes, return the instructions
|
||||
% up to the succed.
|
||||
|
||||
:- pred opt_util__is_succeed_next(list(instruction), list(instruction)).
|
||||
:- mode opt_util__is_succeed_next(in, out) is semidet.
|
||||
|
||||
% Remove the livevals instruction from the list returned by
|
||||
% opt_util__is_proceed_next.
|
||||
|
||||
:- pred opt_util__proceed_no_livevals(list(instruction), list(instruction)).
|
||||
:- mode opt_util__proceed_no_livevals(in, out) is semidet.
|
||||
:- pred opt_util__filter_out_livevals(list(instruction), list(instruction)).
|
||||
:- mode opt_util__filter_out_livevals(in, out) is semidet.
|
||||
|
||||
% Check whether an instruction can possibly branch away.
|
||||
|
||||
@@ -160,26 +175,83 @@ opt_util__is_this_label_next(Label, [Instr | Moreinstr], Remainder) :-
|
||||
opt_util__is_proceed_next(Instrs0, Instrs_between) :-
|
||||
opt_util__skip_comments_labels(Instrs0, Instrs1),
|
||||
Instrs1 = [Instr1 | Instrs2],
|
||||
Instr1 = assign(succip, lval(stackvar(_))) - _,
|
||||
opt_util__skip_comments_labels(Instrs2, Instrs3),
|
||||
( Instr1 = assign(succip, lval(stackvar(_))) - _ ->
|
||||
Instr1use = Instr1,
|
||||
opt_util__skip_comments_labels(Instrs2, Instrs3)
|
||||
;
|
||||
Instr1use = comment("no succip restoration") - "",
|
||||
Instrs3 = Instrs1
|
||||
),
|
||||
Instrs3 = [Instr3 | Instrs4],
|
||||
Instr3 = decr_sp(_) - _,
|
||||
opt_util__skip_comments_labels(Instrs4, Instrs5),
|
||||
( Instr3 = decr_sp(_) - _ ->
|
||||
Instr3use = Instr3,
|
||||
opt_util__skip_comments_labels(Instrs4, Instrs5)
|
||||
;
|
||||
Instr3use = comment("no sp restoration") - "",
|
||||
Instrs5 = Instrs3
|
||||
),
|
||||
Instrs5 = [Instr5 | Instrs6],
|
||||
( Instr5 = livevals(_) - _ ->
|
||||
opt_util__skip_comments_labels(Instrs6, Instrs7),
|
||||
Instr5use = Instr5,
|
||||
opt_util__skip_comments_labels(Instrs6, Instrs7)
|
||||
;
|
||||
Instr5use = comment("no livevals") - "",
|
||||
Instrs7 = Instrs5
|
||||
),
|
||||
Instrs7 = [Instr7 | _],
|
||||
Instr7 = goto(succip) - _,
|
||||
Instrs_between = [Instr1, Instr3, Instr5]
|
||||
; Instr5 = goto(succip) - _ ->
|
||||
Instrs_between = [Instr1, Instr3]
|
||||
;
|
||||
fail
|
||||
).
|
||||
Instrs_between = [Instr1use, Instr3use, Instr5use].
|
||||
|
||||
opt_util__proceed_no_livevals([], []).
|
||||
opt_util__proceed_no_livevals([Instr0 | Instrs0], Instrs) :-
|
||||
opt_util__proceed_no_livevals(Instrs0, Instrs1),
|
||||
opt_util__is_sdproceed_next(Instrs0, Instrs_between) :-
|
||||
opt_util__skip_comments_labels(Instrs0, Instrs1),
|
||||
Instrs1 = [Instr1 | Instrs2],
|
||||
( Instr1 = assign(succip, lval(stackvar(_))) - _ ->
|
||||
Instr1use = Instr1,
|
||||
opt_util__skip_comments_labels(Instrs2, Instrs3)
|
||||
;
|
||||
Instr1use = comment("no succip restoration") - "",
|
||||
Instrs3 = Instrs1
|
||||
),
|
||||
Instrs3 = [Instr3 | Instrs4],
|
||||
( Instr3 = decr_sp(_) - _ ->
|
||||
Instr3use = Instr3,
|
||||
opt_util__skip_comments_labels(Instrs4, Instrs5)
|
||||
;
|
||||
Instr3use = comment("no sp restoration") - "",
|
||||
Instrs5 = Instrs3
|
||||
),
|
||||
Instrs5 = [Instr5 | Instrs6],
|
||||
Instr5 = assign(reg(r(1)), const(_)) - _,
|
||||
opt_util__skip_comments_labels(Instrs6, Instrs7),
|
||||
Instrs7 = [Instr7 | Instrs8],
|
||||
( Instr7 = livevals(_) - _ ->
|
||||
Instr7use = Instr7,
|
||||
opt_util__skip_comments_labels(Instrs8, Instrs9)
|
||||
;
|
||||
Instr7use = comment("no livevals") - "",
|
||||
Instrs9 = Instrs7
|
||||
),
|
||||
Instrs9 = [Instr9 | _],
|
||||
Instr9 = goto(succip) - _,
|
||||
Instrs_between = [Instr1use, Instr3use, Instr5, Instr7use].
|
||||
|
||||
opt_util__is_succeed_next(Instrs0, Instrs_between) :-
|
||||
opt_util__skip_comments_labels(Instrs0, Instrs1),
|
||||
Instrs1 = [Instr1 | Instrs2],
|
||||
( Instr1 = livevals(_) - _ ->
|
||||
Instr1use = Instr1,
|
||||
opt_util__skip_comments_labels(Instrs2, Instrs3)
|
||||
;
|
||||
Instr1use = comment("no livevals") - "",
|
||||
Instrs3 = Instrs1
|
||||
),
|
||||
Instrs3 = [Instr3 | _],
|
||||
Instr3 = goto(do_succeed) - _,
|
||||
Instrs_between = [Instr1use].
|
||||
|
||||
opt_util__filter_out_livevals([], []).
|
||||
opt_util__filter_out_livevals([Instr0 | Instrs0], Instrs) :-
|
||||
opt_util__filter_out_livevals(Instrs0, Instrs1),
|
||||
( Instr0 = livevals(_) - _Comment ->
|
||||
Instrs = Instrs1
|
||||
;
|
||||
|
||||
@@ -9,16 +9,21 @@
|
||||
|
||||
:- module peephole.
|
||||
:- interface.
|
||||
:- import_module llds, options.
|
||||
:- import_module map, llds, options.
|
||||
|
||||
:- pred peephole__optimize(option_table, c_file, c_file).
|
||||
:- mode peephole__optimize(in, in, out) is det.
|
||||
|
||||
% the types are exported only for debugging.
|
||||
|
||||
:- type instmap == map(label, instruction).
|
||||
:- type tailmap == map(label, list(instruction)).
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
|
||||
:- implementation.
|
||||
:- import_module value_number, opt_util, code_util, map, bintree_set.
|
||||
:- import_module string, list, require, std_util.
|
||||
:- import_module value_number, opt_debug, opt_util, code_util, map.
|
||||
:- import_module bintree_set, string, list, require, std_util.
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
|
||||
@@ -111,97 +116,83 @@ peephole__nonrepeat_opts(Options, Instructions0, Instructions) :-
|
||||
% Build up a table showing the first instruction following each label.
|
||||
% Then traverse the instruction list, short-circuiting jump sequences.
|
||||
|
||||
:- type jumpmap == map(label, instruction).
|
||||
:- type procmap == map(label, list(instruction)).
|
||||
|
||||
:- pred peephole__short_circuit(list(instruction), list(instruction), bool).
|
||||
:- mode peephole__short_circuit(in, out, out) is det.
|
||||
|
||||
peephole__short_circuit(Instrs0, Instrs, Mod) :-
|
||||
map__init(Jumpmap0),
|
||||
map__init(Instmap0),
|
||||
map__init(Procmap0),
|
||||
peephole__jumpopt_build_maps(Instrs0, Jumpmap0, Jumpmap,
|
||||
Procmap0, Procmap),
|
||||
% peephole__print_procmap(Procmap),
|
||||
peephole__jumpopt_instr_list(Instrs0, Jumpmap, Procmap, Instrs, Mod).
|
||||
map__init(Sdprocmap0),
|
||||
map__init(Succmap0),
|
||||
peephole__jumpopt_build_maps(Instrs0, Instmap0, Instmap,
|
||||
Procmap0, Procmap, Sdprocmap0, Sdprocmap, Succmap0, Succmap),
|
||||
% opt_debug__print_instmap(Instmap),
|
||||
% opt_debug__print_tailmap(Procmap),
|
||||
% opt_debug__print_tailmap(Sdprocmap),
|
||||
% opt_debug__print_tailmap(Succmap),
|
||||
peephole__jumpopt_instr_list(Instrs0, comment(""),
|
||||
Instmap, Procmap, Sdprocmap, Succmap, Instrs, Mod).
|
||||
|
||||
:- pred peephole__print_procmap(procmap).
|
||||
:- mode peephole__print_procmap(in) is det.
|
||||
:- pred peephole__jumpopt_build_maps(list(instruction), instmap, instmap,
|
||||
tailmap, tailmap, tailmap, tailmap, tailmap, tailmap).
|
||||
:- mode peephole__jumpopt_build_maps(in, di, uo, di, uo, di, uo, di, uo) is det.
|
||||
|
||||
peephole__print_procmap(Procmap) :-
|
||||
write('Procmap:'),
|
||||
nl,
|
||||
map__to_assoc_list(Procmap, Assoclist),
|
||||
peephole__print_proclist(Assoclist).
|
||||
|
||||
:- pred peephole__print_proclist(list(pair(label, list(instruction)))).
|
||||
:- mode peephole__print_proclist(in) is det.
|
||||
|
||||
peephole__print_proclist([]).
|
||||
peephole__print_proclist([Label - Instrs | Assoclist]) :-
|
||||
nl,
|
||||
write(Label),
|
||||
write(' maps to '),
|
||||
write(Instrs),
|
||||
nl,
|
||||
peephole__print_proclist(Assoclist).
|
||||
|
||||
:- pred peephole__jumpopt_build_maps(list(instruction), jumpmap, jumpmap,
|
||||
procmap, procmap).
|
||||
:- mode peephole__jumpopt_build_maps(in, di, uo, di, uo) is det.
|
||||
|
||||
peephole__jumpopt_build_maps([], Jumpmap, Jumpmap, Procmap, Procmap).
|
||||
peephole__jumpopt_build_maps([Instr - _Comment|Instrs],
|
||||
Jumpmap0, Jumpmap, Procmap0, Procmap) :-
|
||||
peephole__jumpopt_build_maps([], Instmap, Instmap, Procmap, Procmap,
|
||||
Sdprocmap, Sdprocmap, Succmap, Succmap).
|
||||
peephole__jumpopt_build_maps([Instr - _Comment|Instrs], Instmap0, Instmap,
|
||||
Procmap0, Procmap, Sdprocmap0, Sdprocmap, Succmap0, Succmap) :-
|
||||
( Instr = label(Label) ->
|
||||
opt_util__skip_comments_livevals(Instrs, Instrs1),
|
||||
( Instrs1 = [Nextinstr | _] ->
|
||||
% write('label '),
|
||||
% write(Label),
|
||||
% write(' maps to '),
|
||||
% write(Nextinstr),
|
||||
% nl,
|
||||
map__set(Jumpmap0, Label, Nextinstr, Jumpmap1)
|
||||
map__set(Instmap0, Label, Nextinstr, Instmap1)
|
||||
;
|
||||
Jumpmap1 = Jumpmap0
|
||||
Instmap1 = Instmap0
|
||||
),
|
||||
( opt_util__is_proceed_next(Instrs, Between) ->
|
||||
% write('label '),
|
||||
% write(Label),
|
||||
% write(' is followed by proceed '),
|
||||
% nl,
|
||||
map__set(Procmap0, Label, Between, Procmap1)
|
||||
( opt_util__is_proceed_next(Instrs, Between1) ->
|
||||
map__set(Procmap0, Label, Between1, Procmap1)
|
||||
;
|
||||
Procmap1 = Procmap0
|
||||
),
|
||||
( opt_util__is_sdproceed_next(Instrs, Between2) ->
|
||||
map__set(Sdprocmap0, Label, Between2, Sdprocmap1)
|
||||
;
|
||||
Sdprocmap1 = Sdprocmap0
|
||||
),
|
||||
( opt_util__is_succeed_next(Instrs, Between3) ->
|
||||
map__set(Succmap0, Label, Between3, Succmap1)
|
||||
;
|
||||
Succmap1 = Succmap0
|
||||
)
|
||||
;
|
||||
Jumpmap1 = Jumpmap0,
|
||||
Procmap1 = Procmap0
|
||||
Instmap1 = Instmap0,
|
||||
Procmap1 = Procmap0,
|
||||
Sdprocmap1 = Sdprocmap0,
|
||||
Succmap1 = Succmap0
|
||||
),
|
||||
peephole__jumpopt_build_maps(Instrs, Jumpmap1, Jumpmap,
|
||||
Procmap1, Procmap).
|
||||
peephole__jumpopt_build_maps(Instrs, Instmap1, Instmap,
|
||||
Procmap1, Procmap, Sdprocmap1, Sdprocmap, Succmap1, Succmap).
|
||||
|
||||
:- pred peephole__jumpopt_instr_list(list(instruction),
|
||||
jumpmap, procmap, list(instruction), bool).
|
||||
:- mode peephole__jumpopt_instr_list(in, in, in, out, out) is det.
|
||||
:- pred peephole__jumpopt_instr_list(list(instruction), instr,
|
||||
instmap, tailmap, tailmap, tailmap, list(instruction), bool).
|
||||
:- mode peephole__jumpopt_instr_list(in, in, in, in, in, in, out, out) is det.
|
||||
|
||||
peephole__jumpopt_instr_list([], _Jumpmap, _Procmap, [], no).
|
||||
peephole__jumpopt_instr_list([Instr0|Moreinstrs0], Jumpmap, Procmap,
|
||||
Instrs, Mod) :-
|
||||
peephole__jumpopt_instr_list([], _Previnstr,
|
||||
_Instmap, _Procmap, _Sdprocmap, _Succmap, [], no).
|
||||
peephole__jumpopt_instr_list([Instr0|Moreinstrs0], Previnstr,
|
||||
Instmap, Procmap, Sdprocmap, Succmap, Instrs, Mod) :-
|
||||
Instr0 = Uinstr0 - Comment0,
|
||||
string__append(Comment0, " (redirected return)", Redirect),
|
||||
(
|
||||
Uinstr0 = call(Proc, label(Retlabel)),
|
||||
map__search(Jumpmap, Retlabel, Retinstr)
|
||||
map__search(Instmap, Retlabel, Retinstr)
|
||||
->
|
||||
peephole__jumpopt_final_dest(Retlabel, Retinstr,
|
||||
Jumpmap, Destlabel, Destinstr),
|
||||
Instmap, Destlabel, Destinstr),
|
||||
( Retlabel = Destlabel ->
|
||||
Newinstrs = [Instr0],
|
||||
Mod0 = no
|
||||
;
|
||||
Newinstrs = [call(Proc, label(Destlabel))
|
||||
- Redirect],
|
||||
Newinstrs = [call(Proc, label(Destlabel)) - Redirect],
|
||||
Mod0 = yes
|
||||
)
|
||||
; Uinstr0 = goto(label(Targetlabel)) ->
|
||||
@@ -210,13 +201,27 @@ peephole__jumpopt_instr_list([Instr0|Moreinstrs0], Jumpmap, Procmap,
|
||||
% is better than shortcircuiting it here
|
||||
Newinstrs = [Instr0],
|
||||
Mod0 = no
|
||||
; Previnstr = if_val(_, label(Iftargetlabel)),
|
||||
Moreinstrs0 = [label(Iftargetlabel) - _|_] ->
|
||||
% eliminating the goto (by the local peephole pass)
|
||||
% is better than shortcircuiting it here
|
||||
Newinstrs = [Instr0],
|
||||
Mod0 = no
|
||||
; map__search(Procmap, Targetlabel, Between) ->
|
||||
list__append(Between, [goto(succip) - "shortcircuit"],
|
||||
Newinstrs),
|
||||
Mod0 = yes
|
||||
; map__search(Jumpmap, Targetlabel, Targetinstr) ->
|
||||
; map__search(Sdprocmap, Targetlabel, Between) ->
|
||||
list__append(Between, [goto(succip) - "shortcircuit"],
|
||||
Newinstrs),
|
||||
Mod0 = yes
|
||||
; map__search(Succmap, Targetlabel, Between) ->
|
||||
list__append(Between, [goto(do_succeed) - "shortcircuit"],
|
||||
Newinstrs),
|
||||
Mod0 = yes
|
||||
; map__search(Instmap, Targetlabel, Targetinstr) ->
|
||||
peephole__jumpopt_final_dest(Targetlabel, Targetinstr,
|
||||
Jumpmap, Destlabel, Destinstr),
|
||||
Instmap, Destlabel, Destinstr),
|
||||
Destinstr = Udestinstr - _Destcomment,
|
||||
string__append("shortcircuited jump: ",
|
||||
Comment0, Shorted),
|
||||
@@ -243,8 +248,13 @@ peephole__jumpopt_instr_list([Instr0|Moreinstrs0], Jumpmap, Procmap,
|
||||
Newinstrs = [Instr0],
|
||||
Mod0 = no
|
||||
),
|
||||
peephole__jumpopt_instr_list(Moreinstrs0, Jumpmap, Procmap,
|
||||
Moreinstrs, Mod1),
|
||||
( ( Uinstr0 = comment(_) ; Uinstr0 = livevals(_) ) ->
|
||||
Newprevinstr = Previnstr
|
||||
;
|
||||
Newprevinstr = Uinstr0
|
||||
),
|
||||
peephole__jumpopt_instr_list(Moreinstrs0, Newprevinstr,
|
||||
Instmap, Procmap, Sdprocmap, Succmap, Moreinstrs, Mod1),
|
||||
list__append(Newinstrs, Moreinstrs, Instrs),
|
||||
( Mod0 = no, Mod1 = no ->
|
||||
Mod = no
|
||||
@@ -252,7 +262,7 @@ peephole__jumpopt_instr_list([Instr0|Moreinstrs0], Jumpmap, Procmap,
|
||||
Mod = yes
|
||||
).
|
||||
|
||||
:- pred peephole__jumpopt_final_dest(label, instruction, jumpmap,
|
||||
:- pred peephole__jumpopt_final_dest(label, instruction, instmap,
|
||||
label, instruction).
|
||||
:- mode peephole__jumpopt_final_dest(in, in, in, out, out) is det.
|
||||
|
||||
@@ -260,11 +270,11 @@ peephole__jumpopt_instr_list([Instr0|Moreinstrs0], Jumpmap, Procmap,
|
||||
% the moment since the compiler never generates code containing
|
||||
% infinite loops, but it may cause problems in the future.
|
||||
|
||||
peephole__jumpopt_final_dest(Srclabel, Srcinstr, Jumpmap,
|
||||
peephole__jumpopt_final_dest(Srclabel, Srcinstr, Instmap,
|
||||
Destlabel, Destinstr) :-
|
||||
(
|
||||
Srcinstr = goto(label(Targetlabel)) - Comment,
|
||||
map__search(Jumpmap, Targetlabel, Targetinstr)
|
||||
map__search(Instmap, Targetlabel, Targetinstr)
|
||||
->
|
||||
% write('goto short-circuit from '),
|
||||
% write(Srclabel),
|
||||
@@ -272,10 +282,10 @@ peephole__jumpopt_final_dest(Srclabel, Srcinstr, Jumpmap,
|
||||
% write(Targetlabel),
|
||||
% nl,
|
||||
peephole__jumpopt_final_dest(Targetlabel, Targetinstr,
|
||||
Jumpmap, Destlabel, Destinstr)
|
||||
Instmap, Destlabel, Destinstr)
|
||||
;
|
||||
Srcinstr = label(Targetlabel) - Comment,
|
||||
map__search(Jumpmap, Targetlabel, Targetinstr)
|
||||
map__search(Instmap, Targetlabel, Targetinstr)
|
||||
->
|
||||
% write('fallthrough short-circuit from '),
|
||||
% write(Srclabel),
|
||||
@@ -283,7 +293,7 @@ peephole__jumpopt_final_dest(Srclabel, Srcinstr, Jumpmap,
|
||||
% write(Targetlabel),
|
||||
% nl,
|
||||
peephole__jumpopt_final_dest(Targetlabel, Targetinstr,
|
||||
Jumpmap, Destlabel, Destinstr)
|
||||
Instmap, Destlabel, Destinstr)
|
||||
;
|
||||
Destlabel = Srclabel,
|
||||
Destinstr = Srcinstr
|
||||
@@ -300,29 +310,57 @@ peephole__jumpopt_final_dest(Srclabel, Srcinstr, Jumpmap,
|
||||
:- pred peephole__local_opt(list(instruction), list(instruction), bool).
|
||||
:- mode peephole__local_opt(in, out, out) is det.
|
||||
|
||||
peephole__local_opt([], [], no).
|
||||
peephole__local_opt([Instr0 - Comment|Instructions0], Instructions, Mod) :-
|
||||
peephole__local_opt(Instructions0, Instructions1, Mod0),
|
||||
peephole__opt_instr(Instr0, Comment, Instructions1, Instructions, Mod1),
|
||||
peephole__local_opt(Instrs0, Instrs, Mod) :-
|
||||
map__init(Procmap0),
|
||||
peephole__local_build_maps(Instrs0, Procmap0, Procmap),
|
||||
peephole__local_opt_2(Instrs0, Instrs, Procmap, Mod).
|
||||
|
||||
:- pred peephole__local_build_maps(list(instruction), tailmap, tailmap).
|
||||
:- mode peephole__local_build_maps(in, di, uo) is det.
|
||||
|
||||
peephole__local_build_maps([], Procmap, Procmap).
|
||||
peephole__local_build_maps([Instr - _Comment|Instrs], Procmap0, Procmap) :-
|
||||
( Instr = label(Label) ->
|
||||
( opt_util__is_proceed_next(Instrs, Between) ->
|
||||
map__set(Procmap0, Label, Between, Procmap1)
|
||||
;
|
||||
Procmap1 = Procmap0
|
||||
)
|
||||
;
|
||||
Procmap1 = Procmap0
|
||||
),
|
||||
peephole__local_build_maps(Instrs, Procmap1, Procmap).
|
||||
|
||||
:- pred peephole__local_opt_2(list(instruction), list(instruction),
|
||||
tailmap, bool).
|
||||
:- mode peephole__local_opt_2(in, out, in, out) is det.
|
||||
|
||||
peephole__local_opt_2([], [], _, no).
|
||||
peephole__local_opt_2([Instr0 - Comment|Instructions0], Instructions,
|
||||
Procmap, Mod) :-
|
||||
peephole__local_opt_2(Instructions0, Instructions1, Procmap, Mod0),
|
||||
peephole__opt_instr(Instr0, Comment, Procmap,
|
||||
Instructions1, Instructions, Mod1),
|
||||
( Mod0 = no, Mod1 = no ->
|
||||
Mod = no
|
||||
;
|
||||
Mod = yes
|
||||
).
|
||||
|
||||
:- pred peephole__opt_instr(instr, string, list(instruction),
|
||||
list(instruction), bool).
|
||||
:- mode peephole__opt_instr(in, in, in, out, out) is det.
|
||||
:- pred peephole__opt_instr(instr, string, tailmap,
|
||||
list(instruction), list(instruction), bool).
|
||||
:- mode peephole__opt_instr(in, in, in, in, out, out) is det.
|
||||
|
||||
peephole__opt_instr(Instr0, Comment0, Instructions0, Instructions, Mod) :-
|
||||
peephole__opt_instr(Instr0, Comment0, Procmap, Instructions0, Instructions,
|
||||
Mod) :-
|
||||
(
|
||||
opt_util__skip_comments(Instructions0, Instructions1),
|
||||
peephole__opt_instr_2(Instr0, Comment0, Instructions1,
|
||||
peephole__opt_instr_2(Instr0, Comment0, Procmap, Instructions1,
|
||||
Instructions2)
|
||||
->
|
||||
( Instructions2 = [Instr2 - Comment2 | Instructions3] ->
|
||||
peephole__opt_instr(Instr2, Comment2, Instructions3,
|
||||
Instructions, _)
|
||||
peephole__opt_instr(Instr2, Comment2, Procmap,
|
||||
Instructions3, Instructions, _)
|
||||
;
|
||||
Instructions = Instructions2
|
||||
),
|
||||
@@ -332,9 +370,9 @@ peephole__opt_instr(Instr0, Comment0, Instructions0, Instructions, Mod) :-
|
||||
Mod = no
|
||||
).
|
||||
|
||||
:- pred peephole__opt_instr_2(instr, string, list(instruction),
|
||||
list(instruction)).
|
||||
:- mode peephole__opt_instr_2(in, in, in, out) is semidet.
|
||||
:- pred peephole__opt_instr_2(instr, string, tailmap,
|
||||
list(instruction), list(instruction)).
|
||||
:- mode peephole__opt_instr_2(in, in, in, in, out) is semidet.
|
||||
|
||||
% A `call' followed by a `proceed' can be replaced with a `tailcall'.
|
||||
%
|
||||
@@ -343,6 +381,7 @@ peephole__opt_instr(Instr0, Comment0, Instructions0, Instructions, Mod) :-
|
||||
% livevals(L1) livevals(L1)
|
||||
% call(Foo, &&ret); tailcall(Foo)
|
||||
% <comments, labels> <comments, labels>
|
||||
% ... ...
|
||||
% ret: => ret:
|
||||
% <comments, labels> <comments, labels>
|
||||
% succip = ... succip = ...
|
||||
@@ -359,30 +398,16 @@ peephole__opt_instr(Instr0, Comment0, Instructions0, Instructions, Mod) :-
|
||||
%
|
||||
% I have some doubt about the validity of using L1 unchanged.
|
||||
|
||||
peephole__opt_instr_2(livevals(Livevals), Comment, Instrs0, Instrs) :-
|
||||
peephole__opt_instr_2(livevals(Livevals), Comment, Procmap, Instrs0, Instrs) :-
|
||||
opt_util__skip_comments(Instrs0, Instrs1),
|
||||
Instrs1 = [call(CodeAddress, label(ContLabel)) - Comment2 | Instrs2],
|
||||
opt_util__is_this_label_next(ContLabel, Instrs2, Instrs3),
|
||||
opt_util__is_proceed_next(Instrs3, Instrs_to_proceed),
|
||||
opt_util__proceed_no_livevals(Instrs_to_proceed, Instrs_to_insert),
|
||||
Instrs1 = [call(CodeAddress, label(ContLabel)) - Comment2 | _],
|
||||
map__search(Procmap, ContLabel, Instrs_to_proceed),
|
||||
opt_util__filter_out_livevals(Instrs_to_proceed, Instrs_to_insert),
|
||||
string__append(Comment, " (redirected return)", Redirect),
|
||||
list__append(Instrs_to_insert,
|
||||
[livevals(Livevals) - Comment2,
|
||||
goto(CodeAddress) - Redirect | Instrs0], Instrs).
|
||||
|
||||
% if a `mkframe' is followed by a `modframe', with the instructions
|
||||
% in between containing only straight-line code, we can delete the
|
||||
% `modframe' and instead just set the redoip directly in the `mkframe'.
|
||||
%
|
||||
% mkframe(D, S, _) => mkframe(D, S, Redoip)
|
||||
% <straightline instrs> <straightline instrs>
|
||||
% modframe(Redoip)
|
||||
|
||||
peephole__opt_instr_2(mkframe(Descr, Slots, _), Comment, Instrs0, Instrs) :-
|
||||
opt_util__next_modframe(Instrs0, [], Redoip, Skipped, Rest),
|
||||
list__append(Skipped, Rest, Instrs1),
|
||||
Instrs = [mkframe(Descr, Slots, Redoip) - Comment | Instrs1].
|
||||
|
||||
% a `goto' can be deleted if the target of the jump is the very
|
||||
% next instruction.
|
||||
%
|
||||
@@ -392,7 +417,8 @@ peephole__opt_instr_2(mkframe(Descr, Slots, _), Comment, Instrs0, Instrs) :-
|
||||
%
|
||||
% dead code after a `goto' is deleted in label-elim.
|
||||
|
||||
peephole__opt_instr_2(goto(label(Label)), _Comment, Instrs0, Instrs) :-
|
||||
peephole__opt_instr_2(goto(label(Label)), _Comment, _Procmap,
|
||||
Instrs0, Instrs) :-
|
||||
opt_util__is_this_label_next(Label, Instrs0, _),
|
||||
Instrs = Instrs0.
|
||||
|
||||
@@ -411,7 +437,8 @@ peephole__opt_instr_2(goto(label(Label)), _Comment, Instrs0, Instrs) :-
|
||||
% <comments, labels> next:
|
||||
% next:
|
||||
|
||||
peephole__opt_instr_2(if_val(Rval, label(Target)), _C1, Instrs0, Instrs) :-
|
||||
peephole__opt_instr_2(if_val(Rval, label(Target)), _C1, _Procmap,
|
||||
Instrs0, Instrs) :-
|
||||
opt_util__skip_comments_livevals(Instrs0, Instrs1),
|
||||
( Instrs1 = [goto(Somewhere) - C2 | Instrs2] ->
|
||||
opt_util__is_this_label_next(Target, Instrs2, _),
|
||||
@@ -422,6 +449,63 @@ peephole__opt_instr_2(if_val(Rval, label(Target)), _C1, Instrs0, Instrs) :-
|
||||
Instrs = Instrs0
|
||||
).
|
||||
|
||||
% if a `mkframe' is followed by a `modframe', with the instructions
|
||||
% in between containing only straight-line code, we can delete the
|
||||
% `modframe' and instead just set the redoip directly in the `mkframe'.
|
||||
%
|
||||
% mkframe(D, S, _) => mkframe(D, S, Redoip)
|
||||
% <straightline instrs> <straightline instrs>
|
||||
% modframe(Redoip)
|
||||
|
||||
peephole__opt_instr_2(mkframe(Descr, Slots, _), Comment, _Procmap,
|
||||
Instrs0, Instrs) :-
|
||||
opt_util__next_modframe(Instrs0, [], Redoip, Skipped, Rest),
|
||||
list__append(Skipped, Rest, Instrs1),
|
||||
Instrs = [mkframe(Descr, Slots, Redoip) - Comment | Instrs1].
|
||||
|
||||
% if a `mkframe' is followed by a test that can fail, we try to
|
||||
% swap the two instructions to avoid doing the mkframe unnecessarily.
|
||||
%
|
||||
% mkframe(D, S, dofail) => if_val(test, redo)
|
||||
% if_val(test, redo/fail) mkframe(D, S, dofail)
|
||||
%
|
||||
% mkframe(D, S, label) => if_val(test, redo)
|
||||
% if_val(test, fail) mkframe(D, S, label)
|
||||
%
|
||||
% mkframe(D, S, label) => mkframe(D, S, label)
|
||||
% if_val(test, redo) if_val(test, label)
|
||||
|
||||
peephole__opt_instr_2(mkframe(Descr, Slots, Redoip), Comment, _Procmap,
|
||||
Instrs0, Instrs) :-
|
||||
opt_util__skip_comments_livevals(Instrs0, Instrs1),
|
||||
Instrs1 = [Instr1 | Instrs2],
|
||||
Instr1 = if_val(Test, Target) - Comment2,
|
||||
(
|
||||
Redoip = do_fail,
|
||||
( Target = do_redo ; Target = do_fail)
|
||||
->
|
||||
Instrs = [if_val(Test, do_redo) - Comment2,
|
||||
mkframe(Descr, Slots, do_fail) - Comment | Instrs2]
|
||||
;
|
||||
Redoip = label(_)
|
||||
->
|
||||
(
|
||||
Target = do_fail
|
||||
->
|
||||
Instrs = [if_val(Test, do_redo) - Comment2,
|
||||
mkframe(Descr, Slots, Redoip) - Comment | Instrs2]
|
||||
;
|
||||
Target = do_redo
|
||||
->
|
||||
Instrs = [mkframe(Descr, Slots, Redoip) - Comment,
|
||||
if_val(Test, Redoip) - Comment2 | Instrs2]
|
||||
;
|
||||
fail
|
||||
)
|
||||
;
|
||||
fail
|
||||
).
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
|
||||
% Build up a table showing which labels are branched to.
|
||||
|
||||
@@ -14,18 +14,658 @@
|
||||
:- pred value_number__optimize(list(instruction), list(instruction)).
|
||||
:- mode value_number__optimize(in, out) is det.
|
||||
|
||||
% the rest are exported only for debugging.
|
||||
|
||||
:- type lvalset == bintree_set(lval).
|
||||
:- type livemap == map(label, lvalset).
|
||||
|
||||
:- type vn == int.
|
||||
|
||||
:- type lval_to_vn_table == map(vn_lval, vn).
|
||||
:- type rval_to_vn_table == map(vn_rval, vn).
|
||||
:- type vn_to_rval_table == map(vn, vn_rval).
|
||||
:- type vn_to_uses_table == map(vn, int).
|
||||
:- type vn_to_locs_table == map(vn, list(vn_lval)).
|
||||
:- type loc_to_vn_table == map(vn_lval, vn).
|
||||
|
||||
:- type vn_tables ---> vn_tables(vn, lval_to_vn_table, rval_to_vn_table,
|
||||
vn_to_rval_table, vn_to_uses_table,
|
||||
vn_to_locs_table, loc_to_vn_table).
|
||||
|
||||
:- type vn_lval ---> vn_reg(reg)
|
||||
; vn_stackvar(int)
|
||||
; vn_framevar(int)
|
||||
; vn_succip
|
||||
; vn_maxfr
|
||||
; vn_curredoip
|
||||
; vn_hp
|
||||
; vn_sp
|
||||
; vn_field(tag, vn, int) % lval
|
||||
; vn_temp(int).
|
||||
|
||||
% these lvals do not have vn_lval parallels
|
||||
% lvar(var)
|
||||
|
||||
:- type vn_rval ---> vn_origlval(vn_lval)
|
||||
; vn_mkword(tag, vn) % rval
|
||||
; vn_const(rval_const)
|
||||
; vn_field(tag, vn, int) % rval
|
||||
; vn_unop(unary_op, vn) % rval
|
||||
; vn_binop(operator, vn, vn). % rval, rval
|
||||
|
||||
% these rvals do not have vn_rval parallels
|
||||
% vn_create(tag, list(rval))
|
||||
% var(var)
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
|
||||
:- implementation.
|
||||
:- import_module code_util, map, bintree_set, string, require, std_util.
|
||||
:- import_module opt_util, opt_debug, map, bintree_set.
|
||||
:- import_module int, string, require, std_util.
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
% XXX map__update/set should be det, should call error if key not already there
|
||||
% XXX should simplify expression
|
||||
|
||||
% Find straight-line code sequences and optimize them using
|
||||
% value numbering.
|
||||
|
||||
value_number__optimize(Instructions, Instructions).
|
||||
value_number__optimize(Instrs0, Instrs) :-
|
||||
map__init(Livemap0),
|
||||
bintree_set__init(Livevals0),
|
||||
list__reverse(Instrs0, Backinstrs),
|
||||
value_number__build_livemap(Backinstrs, Livevals0, no,
|
||||
Livemap0, Livemap),
|
||||
value_number__insert_livemap(Livemap, Instrs0, Instrs1),
|
||||
value_number__opt_instrs(Instrs1, Livemap, Instrs).
|
||||
|
||||
:- end_module value_number.
|
||||
:- pred value_number__insert_livemap(livemap, list(instruction),
|
||||
list(instruction)).
|
||||
:- mode value_number__insert_livemap(in, di, uo) is det.
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
value_number__insert_livemap(_Livemap, [], []).
|
||||
value_number__insert_livemap(Livemap, [Instr0 | Instrs0], Instrs) :-
|
||||
value_number__insert_livemap(Livemap, Instrs0, Instrs1),
|
||||
Instr0 = Uinstr0 - _Comment,
|
||||
( Uinstr0 = label(Label) ->
|
||||
( map__search(Livemap, Label, Livevals) ->
|
||||
Instrs = [Instr0, livevals(Livevals) - "auto" | Instrs1]
|
||||
;
|
||||
error("no livevals info about a label")
|
||||
)
|
||||
;
|
||||
Instrs = [Instr0 | Instrs1]
|
||||
).
|
||||
|
||||
:- pred value_number__build_livemap(list(instruction), lvalset,
|
||||
bool, livemap, livemap).
|
||||
:- mode value_number__build_livemap(in, in, in, di, uo) is det.
|
||||
|
||||
value_number__build_livemap([], _, _, Livemap, Livemap).
|
||||
value_number__build_livemap([Instr|Moreinstrs], Livevals0, Ccode0,
|
||||
Livemap0, Livemap) :-
|
||||
Instr = Uinstr - _Comment,
|
||||
( Uinstr = call(_, _) ->
|
||||
opt_util__skip_comments(Moreinstrs, Moreinstrs1),
|
||||
(
|
||||
Moreinstrs1 = [Nextinstr | Evenmoreinstrs],
|
||||
Nextinstr = Nextuinstr - Nextcomment,
|
||||
Nextuinstr = livevals(Livevals2prime)
|
||||
->
|
||||
Livevals2 = Livevals2prime,
|
||||
Livemap1 = Livemap0,
|
||||
Moreinstrs2 = Evenmoreinstrs,
|
||||
Ccode1 = Ccode0
|
||||
;
|
||||
% Moreinstrs1 = [Nextinstr | Evenmoreinstrs],
|
||||
% Nextinstr = Nextuinstr - Nextcomment,
|
||||
% write(Instr),
|
||||
% nl,
|
||||
% write(Nextinstr),
|
||||
% nl,
|
||||
% Livevals2 = Livevals0,
|
||||
% Livemap1 = Livemap0,
|
||||
% Moreinstrs2 = Evenmoreinstrs,
|
||||
% Ccode1 = Ccode0
|
||||
error("call not preceded by livevals")
|
||||
)
|
||||
; Uinstr = goto(Codeaddr) ->
|
||||
opt_util__skip_comments(Moreinstrs, Moreinstrs1),
|
||||
opt_util__livevals_addr(Codeaddr, Livevals_needed),
|
||||
( Livevals_needed = yes ->
|
||||
(
|
||||
Moreinstrs1 = [Nextinstr | Evenmoreinstrs],
|
||||
Nextinstr = Nextuinstr - Nextcomment,
|
||||
Nextuinstr = livevals(Livevals2prime)
|
||||
->
|
||||
Livevals2 = Livevals2prime,
|
||||
Livemap1 = Livemap0,
|
||||
Moreinstrs2 = Evenmoreinstrs,
|
||||
Ccode1 = Ccode0
|
||||
;
|
||||
error("tailcall not preceded by livevals")
|
||||
)
|
||||
; Codeaddr = label(Label) ->
|
||||
( map__search(Livemap0, Label, Livevals2prime) ->
|
||||
Livevals2 = Livevals2prime,
|
||||
Livemap1 = Livemap0,
|
||||
Moreinstrs2 = Moreinstrs,
|
||||
Ccode1 = Ccode0
|
||||
;
|
||||
error("cannot handle backwards local gotos")
|
||||
)
|
||||
;
|
||||
Livevals2 = Livevals0,
|
||||
Livemap1 = Livemap0,
|
||||
Moreinstrs2 = Moreinstrs,
|
||||
Ccode1 = Ccode0
|
||||
)
|
||||
; Uinstr = label(Label) ->
|
||||
( Ccode0 = no ->
|
||||
map__set(Livemap0, Label, Livevals0, Livemap1)
|
||||
;
|
||||
Livemap1 = Livemap0
|
||||
),
|
||||
Livevals2 = Livevals0,
|
||||
Moreinstrs2 = Moreinstrs,
|
||||
Ccode1 = Ccode0
|
||||
; ( Uinstr = incr_sp(_) ; Uinstr = decr_sp(_)) ->
|
||||
value_number__make_live(lval(sp), Livevals0, Livevals2),
|
||||
Livemap1 = Livemap0,
|
||||
Moreinstrs2 = Moreinstrs,
|
||||
Ccode1 = Ccode0
|
||||
; Uinstr = incr_hp(_) ->
|
||||
value_number__make_live(lval(hp), Livevals0, Livevals2),
|
||||
Livemap1 = Livemap0,
|
||||
Moreinstrs2 = Moreinstrs,
|
||||
Ccode1 = Ccode0
|
||||
; Uinstr = if_val(Rval, _) ->
|
||||
value_number__make_live(Rval, Livevals0, Livevals2),
|
||||
Livemap1 = Livemap0,
|
||||
Moreinstrs2 = Moreinstrs,
|
||||
Ccode1 = Ccode0
|
||||
; Uinstr = assign(Lval, Rval) ->
|
||||
value_number__make_dead(Lval, Livevals0, Livevals1),
|
||||
value_number__make_live(Rval, Livevals1, Livevals2),
|
||||
Livemap1 = Livemap0,
|
||||
Moreinstrs2 = Moreinstrs,
|
||||
Ccode1 = Ccode0
|
||||
; Uinstr = c_code(_) ->
|
||||
Livemap1 = Livemap0,
|
||||
Livevals2 = Livevals0,
|
||||
Moreinstrs2 = Moreinstrs,
|
||||
Ccode1 = yes
|
||||
;
|
||||
Livemap1 = Livemap0,
|
||||
Livevals2 = Livevals0,
|
||||
Moreinstrs2 = Moreinstrs,
|
||||
Ccode1 = Ccode0
|
||||
),
|
||||
value_number__build_livemap(Moreinstrs2, Livevals2, Ccode1,
|
||||
Livemap1, Livemap).
|
||||
|
||||
% Set all lvals found in this rval to live.
|
||||
|
||||
:- pred value_number__make_live(rval, lvalset, lvalset).
|
||||
:- mode value_number__make_live(in, di, uo) is det.
|
||||
|
||||
value_number__make_live(lval(Lval), Livevals0, Livevals) :-
|
||||
bintree_set__insert(Livevals0, Lval, Livevals).
|
||||
value_number__make_live(var(_), Livevals0, Livevals0) :-
|
||||
error("var rval should not propagate to value_number").
|
||||
value_number__make_live(create(_, _, _), Livevals0, Livevals0) :-
|
||||
error("create rval should not propagate to value_number").
|
||||
value_number__make_live(mkword(_, Rval), Livevals0, Livevals) :-
|
||||
value_number__make_live(Rval, Livevals0, Livevals).
|
||||
value_number__make_live(field(_, Rval, _), Livevals0, Livevals) :-
|
||||
value_number__make_live(Rval, Livevals0, Livevals).
|
||||
value_number__make_live(const(_), Livevals0, Livevals0).
|
||||
value_number__make_live(unop(_, Rval), Livevals0, Livevals) :-
|
||||
value_number__make_live(Rval, Livevals0, Livevals).
|
||||
value_number__make_live(binop(_, Rval1, Rval2), Livevals0, Livevals) :-
|
||||
value_number__make_live(Rval1, Livevals0, Livevals1),
|
||||
value_number__make_live(Rval2, Livevals1, Livevals).
|
||||
|
||||
% Set this lval to dead.
|
||||
|
||||
:- pred value_number__make_dead(lval, lvalset, lvalset).
|
||||
:- mode value_number__make_dead(in, di, uo) is det.
|
||||
|
||||
value_number__make_dead(Lval, Livevals0, Livevals) :-
|
||||
bintree_set__delete(Livevals0, Lval, Livevals).
|
||||
|
||||
% Optimize instructions, assume we are outside of a block.
|
||||
|
||||
:- pred value_number__opt_instrs(list(instruction), livemap,
|
||||
list(instruction)).
|
||||
:- mode value_number__opt_instrs(in, in, out) is det.
|
||||
|
||||
value_number__opt_instrs([], _, []).
|
||||
value_number__opt_instrs([Instr0 | Instrs0], Livemap, Instrs) :-
|
||||
Instr0 = Uinstr0 - _Comment0,
|
||||
(
|
||||
Uinstr0 = label(Label),
|
||||
map__search(Livemap, Label, _Livevals)
|
||||
->
|
||||
value_number__init_tables(Vn_tables0),
|
||||
value_number__opt_block(Instrs0, Vn_tables0, Livemap, no,
|
||||
Instrs1),
|
||||
Instrs = [Instr0 | Instrs1]
|
||||
% value_number__opt_instrs(Instrs0, Livemap, Instrs1),
|
||||
% Instrs = [Instr0 | Instrs1]
|
||||
;
|
||||
value_number__opt_instrs(Instrs0, Livemap, Instrs1),
|
||||
Instrs = [Instr0 | Instrs1]
|
||||
).
|
||||
|
||||
% Initialize the tables for optimizing a block of instructions.
|
||||
|
||||
:- pred value_number__init_tables(vn_tables).
|
||||
:- mode value_number__init_tables(out) is det.
|
||||
|
||||
value_number__init_tables(Vn_tables) :-
|
||||
map__init(Lval_to_vn_table0),
|
||||
map__init(Rval_to_vn_table0),
|
||||
map__init(Vn_to_rval_table0),
|
||||
map__init(Vn_to_uses_table0),
|
||||
map__init(Vn_to_locs_table0),
|
||||
map__init(Loc_to_vn_table0),
|
||||
Vn_tables = vn_tables(0,
|
||||
Lval_to_vn_table0, Rval_to_vn_table0,
|
||||
Vn_to_rval_table0, Vn_to_uses_table0,
|
||||
Vn_to_locs_table0, Loc_to_vn_table0).
|
||||
|
||||
% Optimize instructions, assume we are inside of a block.
|
||||
|
||||
:- pred value_number__opt_block(list(instruction), vn_tables, livemap,
|
||||
maybe(bintree_set(lval)), list(instruction)).
|
||||
:- mode value_number__opt_block(in, in, in, in, out) is det.
|
||||
|
||||
value_number__opt_block([], _Vn_tables, _Livemap, _Last_livevals, []) :-
|
||||
error("block has no terminator").
|
||||
value_number__opt_block([Instr0 | Instrs0],
|
||||
Vn_tables, Livemap, Last_livevals, Instrs) :-
|
||||
value_number__handle_instr(Instr0, Vn_tables, Livemap,
|
||||
Last_livevals, Instrs0, Instrs).
|
||||
|
||||
:- pred value_number__handle_instr(instruction, vn_tables, livemap,
|
||||
maybe(bintree_set(lval)), list(instruction), list(instruction)).
|
||||
:- mode value_number__handle_instr(in, in, in, in, in, out) is det.
|
||||
|
||||
value_number__handle_instr(Instr0, Vn_tables0, Livemap, Last_livevals,
|
||||
Instrs0, Instrs) :-
|
||||
% should be converted to if-then-elses when np efficiency is important
|
||||
Instr0 = Uinstr0 - Comment,
|
||||
(
|
||||
Uinstr0 = comment(_),
|
||||
value_number__opt_block(Instrs0, Vn_tables0, Livemap,
|
||||
no, Instrs1),
|
||||
Instrs = [Instr0 | Instrs1]
|
||||
;
|
||||
Uinstr0 = livevals(Livevals),
|
||||
value_number__opt_block(Instrs0, Vn_tables0, Livemap,
|
||||
yes(Livevals), Instrs1),
|
||||
Instrs = [Instr0 | Instrs1]
|
||||
;
|
||||
Uinstr0 = block(_, _),
|
||||
error("block should not be found in handle_instr")
|
||||
;
|
||||
Uinstr0 = assign(Lval, Rval),
|
||||
% the next call does the counting of the new use
|
||||
value_number__use_rval_find_vn(Rval, Vn,
|
||||
Vn_tables0, Vn_tables1),
|
||||
value_number__lval_to_vnlval(Lval, Vn_lval,
|
||||
Vn_tables1, Vn_tables2),
|
||||
Vn_tables2 = vn_tables(Next_vn2,
|
||||
Lval_to_vn_table2, Rval_to_vn_table2,
|
||||
Vn_to_rval_table2, Vn_to_uses_table2,
|
||||
Vn_to_locs_table2, Loc_to_vn_table2),
|
||||
( map__search(Lval_to_vn_table2, Vn_lval, Old_vn) ->
|
||||
map__lookup(Vn_to_uses_table2, Old_vn, Old_vn_uses2),
|
||||
Old_vn_uses3 is Old_vn_uses2 - 1,
|
||||
map__set(Vn_to_uses_table2, Old_vn, Old_vn_uses3,
|
||||
Vn_to_uses_table3)
|
||||
;
|
||||
Vn_to_uses_table3 = Vn_to_uses_table2
|
||||
),
|
||||
map__set(Lval_to_vn_table2, Vn_lval, Vn, Lval_to_vn_table3),
|
||||
Vn_tables3 = vn_tables(Next_vn2,
|
||||
Lval_to_vn_table3, Rval_to_vn_table2,
|
||||
Vn_to_rval_table2, Vn_to_uses_table3,
|
||||
Vn_to_locs_table2, Loc_to_vn_table2),
|
||||
value_number__opt_block(Instrs0, Vn_tables3, Livemap,
|
||||
no, Instrs1),
|
||||
Instrs = [Instr0 | Instrs1]
|
||||
;
|
||||
Uinstr0 = call(_, _),
|
||||
( Last_livevals = yes(Livevals) ->
|
||||
% flush
|
||||
true
|
||||
;
|
||||
error("call not preceded by livevals")
|
||||
),
|
||||
value_number__opt_instrs(Instrs0, Livemap, Instrs1),
|
||||
opt_debug__dump_tables(Vn_tables0, Newcomment),
|
||||
Instrs = [comment(Newcomment) - "", Instr0 | Instrs1]
|
||||
;
|
||||
Uinstr0 = mkframe(_, _, _),
|
||||
value_number__opt_block(Instrs0, Vn_tables0, Livemap,
|
||||
no, Instrs1),
|
||||
Instrs = [Instr0 | Instrs1]
|
||||
;
|
||||
Uinstr0 = modframe(_),
|
||||
value_number__opt_block(Instrs0, Vn_tables0, Livemap,
|
||||
no, Instrs1),
|
||||
Instrs = [Instr0 | Instrs1]
|
||||
;
|
||||
Uinstr0 = label(_),
|
||||
opt_util__skip_comments(Instrs0, Instrs1),
|
||||
( Instrs1 = [livevals(_Nextlivevals) - _ | _] ->
|
||||
% XXX flush all these livevals
|
||||
true
|
||||
;
|
||||
% flush all livevals or maybe abort
|
||||
true
|
||||
),
|
||||
value_number__opt_block(Instrs1, Vn_tables0, Livemap,
|
||||
no, Instrs2),
|
||||
Instrs = [Instr0 | Instrs2]
|
||||
% opt_debug__dump_label(L, L_str),
|
||||
% string__append_list(["label ", L_str, " in handle_instr"], Str),
|
||||
% error(Str)
|
||||
;
|
||||
Uinstr0 = goto(_),
|
||||
( Last_livevals = yes(Livevals) ->
|
||||
% flush
|
||||
true
|
||||
;
|
||||
error("goto not preceded by livevals")
|
||||
),
|
||||
value_number__opt_instrs(Instrs0, Livemap, Instrs1),
|
||||
opt_debug__dump_tables(Vn_tables0, Newcomment),
|
||||
Instrs = [comment(Newcomment) - "", Instr0 | Instrs1]
|
||||
;
|
||||
Uinstr0 = computed_goto(_, _),
|
||||
( Last_livevals = yes(Livevals) ->
|
||||
% flush
|
||||
true
|
||||
;
|
||||
error("computed goto not preceded by livevals")
|
||||
),
|
||||
value_number__opt_instrs(Instrs0, Livemap, Instrs1),
|
||||
opt_debug__dump_tables(Vn_tables0, Newcomment),
|
||||
Instrs = [comment(Newcomment) - "", Instr0 | Instrs1]
|
||||
;
|
||||
Uinstr0 = c_code(_),
|
||||
error("c_code in handle_instr")
|
||||
;
|
||||
Uinstr0 = if_val(_, _),
|
||||
% XXX flush values live at Code_addr
|
||||
value_number__opt_block(Instrs0, Vn_tables0, Livemap,
|
||||
no, Instrs1),
|
||||
opt_debug__dump_tables(Vn_tables0, Newcomment),
|
||||
Instrs = [comment(Newcomment) - "", Instr0 | Instrs1]
|
||||
;
|
||||
Uinstr0 = incr_sp(N),
|
||||
value_number__opt_block(Instrs0, Vn_tables0, Livemap,
|
||||
no, Instrs1),
|
||||
Instrs = [Instr0 | Instrs1]
|
||||
;
|
||||
Uinstr0 = decr_sp(N),
|
||||
value_number__opt_block(Instrs0, Vn_tables0, Livemap,
|
||||
no, Instrs1),
|
||||
Instrs = [Instr0 | Instrs1]
|
||||
;
|
||||
Uinstr0 = incr_hp(N),
|
||||
value_number__handle_instr(assign(hp,
|
||||
binop((+), lval(hp), const(int_const(N)))) - Comment,
|
||||
Vn_tables0, Livemap, Last_livevals, Instrs0, Instrs)
|
||||
).
|
||||
|
||||
:- pred value_number__use_rval_find_vn(rval, vn, vn_tables, vn_tables).
|
||||
:- mode value_number__use_rval_find_vn(in, out, di, uo) is det.
|
||||
|
||||
value_number__use_rval_find_vn(lval(Lval), Vn, Vn_tables0, Vn_tables) :-
|
||||
value_number__use_lval_find_vn(Lval, Vn, Vn_tables0, Vn_tables).
|
||||
value_number__use_rval_find_vn(var(_), _, _Vn_tables, _) :-
|
||||
error("value_number should never get rval: var").
|
||||
value_number__use_rval_find_vn(create(_, _, _), _, _Vn_tables, _) :-
|
||||
error("value_number should never get rval: create").
|
||||
value_number__use_rval_find_vn(mkword(Tag, Rval), Vn, Vn_tables0, Vn_tables) :-
|
||||
value_number__use_rval_find_vn(Rval, Sub_vn, Vn_tables0, Vn_tables1),
|
||||
value_number__use_vnrval_find_vn(vn_mkword(Tag, Sub_vn), Vn,
|
||||
Vn_tables1, Vn_tables).
|
||||
value_number__use_rval_find_vn(unop(Op, Rval), Vn, Vn_tables0, Vn_tables) :-
|
||||
value_number__use_rval_find_vn(Rval, Sub_vn, Vn_tables0, Vn_tables1),
|
||||
value_number__use_vnrval_find_vn(vn_unop(Op, Sub_vn), Vn,
|
||||
Vn_tables1, Vn_tables).
|
||||
value_number__use_rval_find_vn(const(Const), Vn, Vn_tables0, Vn_tables) :-
|
||||
value_number__use_vnrval_find_vn(vn_const(Const), Vn,
|
||||
Vn_tables0, Vn_tables).
|
||||
value_number__use_rval_find_vn(field(Tag, Rval, Slot), Vn,
|
||||
Vn_tables0, Vn_tables) :-
|
||||
value_number__use_rval_find_vn(Rval, Sub_vn, Vn_tables0, Vn_tables1),
|
||||
value_number__use_vnrval_find_vn(vn_field(Tag, Sub_vn, Slot), Vn,
|
||||
Vn_tables1, Vn_tables).
|
||||
value_number__use_rval_find_vn(binop(Op, Left_rval, Right_rval), Vn,
|
||||
Vn_tables0, Vn_tables) :-
|
||||
value_number__use_rval_find_vn(Left_rval, Left_vn,
|
||||
Vn_tables0, Vn_tables1),
|
||||
value_number__use_rval_find_vn(Right_rval, Right_vn,
|
||||
Vn_tables1, Vn_tables2),
|
||||
value_number__use_vnrval_find_vn(vn_binop(Op, Left_vn, Right_vn), Vn,
|
||||
Vn_tables2, Vn_tables).
|
||||
|
||||
:- pred value_number__use_vnrval_find_vn(vn_rval, vn, vn_tables, vn_tables).
|
||||
:- mode value_number__use_vnrval_find_vn(in, out, di, uo) is det.
|
||||
|
||||
value_number__use_vnrval_find_vn(Vn_rval, Vn, Vn_tables0, Vn_tables) :-
|
||||
value_number__simplify_vnrval(Vn_rval, Vn_rval1,
|
||||
Vn_tables0, Vn_tables1),
|
||||
value_number__lookup_vnrval(Vn_rval1, Vn, Vn_tables1, Vn_tables).
|
||||
|
||||
% Simplify the vnrval by partially evaluating expressions involving
|
||||
% integer constants. To make this simpler, swap the arguments of
|
||||
% commutative expressions around to put the constants on the right
|
||||
% side.
|
||||
%
|
||||
% The simplification has to be done on vn_rvals and not on rvals
|
||||
% even though this complicates the code. The reason is that an
|
||||
% expression such as r1 + 4 can be simplified if we know that
|
||||
% r1 was defined as r2 + 8.
|
||||
%
|
||||
% This code should decrement the use counts of value numbers that
|
||||
% the incoming vn_rval refers to that the outgoing vn_rval does not,
|
||||
% but this is not yet implemented. In any case, we probably don't need
|
||||
% accurate use counts on constants.
|
||||
|
||||
:- pred value_number__simplify_vnrval(vn_rval, vn_rval, vn_tables, vn_tables).
|
||||
:- mode value_number__simplify_vnrval(in, out, di, uo) is det.
|
||||
|
||||
value_number__simplify_vnrval(Vn_rval0, Vn_rval, Vn_tables0, Vn_tables) :-
|
||||
Vn_tables0 = vn_tables(_Next_vn0,
|
||||
_Lval_to_vn_table0, _Rval_to_vn_table0,
|
||||
Vn_to_rval_table0, _Vn_to_uses_table0,
|
||||
_Vn_to_locs_table0, _Loc_to_vn_table0),
|
||||
( Vn_rval0 = vn_binop((+), Vn1, Vn2) ->
|
||||
map__lookup(Vn_to_rval_table0, Vn1, Vn_rval1),
|
||||
map__lookup(Vn_to_rval_table0, Vn2, Vn_rval2),
|
||||
( Vn_rval1 = vn_const(int_const(I1)) ->
|
||||
( Vn_rval2 = vn_const(int_const(I2)) ->
|
||||
I is I1 + I2,
|
||||
Vn_rval = vn_const(int_const(I)),
|
||||
Vn_tables = Vn_tables0
|
||||
; Vn_rval2 = vn_binop((+), Vn21, Vn22) ->
|
||||
map__lookup(Vn_to_rval_table0, Vn22, Vn_rval22),
|
||||
( Vn_rval22 = vn_const(int_const(I22)) ->
|
||||
I is I1 + I22,
|
||||
value_number__use_vnrval_find_vn(
|
||||
vn_const(int_const(I)), Vn_i,
|
||||
Vn_tables0, Vn_tables),
|
||||
Vn_rval = vn_binop((+), Vn21, Vn_i)
|
||||
;
|
||||
Vn_rval = vn_binop((+), Vn2, Vn1),
|
||||
Vn_tables = Vn_tables0
|
||||
)
|
||||
;
|
||||
Vn_rval = vn_binop((+), Vn2, Vn1),
|
||||
Vn_tables = Vn_tables0
|
||||
)
|
||||
; Vn_rval1 = vn_binop((+), Vn11, Vn12) ->
|
||||
map__lookup(Vn_to_rval_table0, Vn12, Vn_rval12),
|
||||
( Vn_rval12 = vn_const(int_const(I12)) ->
|
||||
( Vn_rval2 = vn_const(int_const(I2)) ->
|
||||
I is I12 + I2,
|
||||
value_number__use_vnrval_find_vn(
|
||||
vn_const(int_const(I)), Vn_i,
|
||||
Vn_tables0, Vn_tables),
|
||||
Vn_rval = vn_binop((+), Vn11, Vn_i)
|
||||
; Vn_rval2 = vn_binop((+), Vn21, Vn22) ->
|
||||
map__lookup(Vn_to_rval_table0, Vn22, Vn_rval22),
|
||||
( Vn_rval22 = vn_const(int_const(I22)) ->
|
||||
I is I12 + I22,
|
||||
value_number__use_vnrval_find_vn(
|
||||
vn_binop((+), Vn11, Vn21), Vn_e,
|
||||
Vn_tables0, Vn_tables1),
|
||||
value_number__use_vnrval_find_vn(
|
||||
vn_const(int_const(I)), Vn_i,
|
||||
Vn_tables1, Vn_tables),
|
||||
Vn_rval = vn_binop((+), Vn_e, Vn_i)
|
||||
;
|
||||
value_number__use_vnrval_find_vn(
|
||||
vn_binop((+), Vn2, Vn11), Vn_e,
|
||||
Vn_tables0, Vn_tables),
|
||||
Vn_rval = vn_binop((+), Vn_e, Vn12)
|
||||
)
|
||||
;
|
||||
Vn_rval = Vn_rval0,
|
||||
Vn_tables = Vn_tables0
|
||||
)
|
||||
;
|
||||
Vn_rval = vn_binop((+), Vn2, Vn1),
|
||||
Vn_tables = Vn_tables0
|
||||
)
|
||||
;
|
||||
Vn_rval = Vn_rval0,
|
||||
Vn_tables = Vn_tables0
|
||||
)
|
||||
; Vn_rval0 = vn_binop((-), Vn1, Vn2) ->
|
||||
map__lookup(Vn_to_rval_table0, Vn2, Vn_rval2),
|
||||
( Vn_rval2 = vn_const(int_const(I2)) ->
|
||||
NI2 is 0 - I2,
|
||||
value_number__use_vnrval_find_vn(vn_const(int_const(NI2)),
|
||||
Vn2prime, Vn_tables0, Vn_tables1),
|
||||
value_number__simplify_vnrval(vn_binop((+), Vn1, Vn2prime),
|
||||
Vn_rval, Vn_tables1, Vn_tables)
|
||||
;
|
||||
% XXX more simplification opportunities exist
|
||||
Vn_rval = Vn_rval0,
|
||||
Vn_tables = Vn_tables0
|
||||
)
|
||||
;
|
||||
% XXX more simplification opportunities exist
|
||||
Vn_rval = Vn_rval0,
|
||||
Vn_tables = Vn_tables0
|
||||
).
|
||||
|
||||
:- pred value_number__lookup_vnrval(vn_rval, vn, vn_tables, vn_tables).
|
||||
:- mode value_number__lookup_vnrval(in, out, di, uo) is det.
|
||||
|
||||
value_number__lookup_vnrval(Vn_rval, Vn, Vn_tables0, Vn_tables) :-
|
||||
Vn_tables0 = vn_tables(Next_vn0,
|
||||
Lval_to_vn_table0, Rval_to_vn_table0,
|
||||
Vn_to_rval_table0, Vn_to_uses_table0,
|
||||
Vn_to_locs_table0, Loc_to_vn_table0),
|
||||
( map__search(Rval_to_vn_table0, Vn_rval, Vn_prime) ->
|
||||
Vn = Vn_prime,
|
||||
map__lookup(Vn_to_uses_table0, Vn, Usecount),
|
||||
Usecount1 is Usecount + 1,
|
||||
map__set(Vn_to_uses_table0, Vn, Usecount1, Vn_to_uses_table1),
|
||||
Vn_tables = vn_tables(Next_vn0,
|
||||
Lval_to_vn_table0, Rval_to_vn_table0,
|
||||
Vn_to_rval_table0, Vn_to_uses_table1,
|
||||
Vn_to_locs_table0, Loc_to_vn_table0)
|
||||
;
|
||||
Vn = Next_vn0,
|
||||
Next_vn1 is Next_vn0 + 1,
|
||||
map__set(Rval_to_vn_table0, Vn_rval, Vn, Rval_to_vn_table1),
|
||||
map__set(Vn_to_rval_table0, Vn, Vn_rval, Vn_to_rval_table1),
|
||||
map__set(Vn_to_uses_table0, Vn, 1, Vn_to_uses_table1),
|
||||
Vn_tables = vn_tables(Next_vn1,
|
||||
Lval_to_vn_table0, Rval_to_vn_table1,
|
||||
Vn_to_rval_table1, Vn_to_uses_table1,
|
||||
Vn_to_locs_table0, Loc_to_vn_table0)
|
||||
).
|
||||
|
||||
:- pred value_number__use_lval_find_vn(lval, vn, vn_tables, vn_tables).
|
||||
:- mode value_number__use_lval_find_vn(in, out, di, uo) is det.
|
||||
|
||||
value_number__use_lval_find_vn(Lval, Vn, Vn_tables0, Vn_tables) :-
|
||||
value_number__lval_to_vnlval(Lval, Vn_lval, Vn_tables0, Vn_tables1),
|
||||
Vn_tables1 = vn_tables(Next_vn1,
|
||||
Lval_to_vn_table1, Rval_to_vn_table1,
|
||||
Vn_to_rval_table1, Vn_to_uses_table1,
|
||||
Vn_to_locs_table1, Loc_to_vn_table1),
|
||||
( map__search(Lval_to_vn_table1, Vn_lval, Vn_prime) ->
|
||||
Vn = Vn_prime,
|
||||
map__lookup(Vn_to_uses_table1, Vn, Usecount1),
|
||||
Usecount2 is Usecount1 + 1,
|
||||
map__set(Vn_to_uses_table1, Vn, Usecount2, Vn_to_uses_table2),
|
||||
Vn_tables = vn_tables(Next_vn1,
|
||||
Lval_to_vn_table1, Rval_to_vn_table1,
|
||||
Vn_to_rval_table1, Vn_to_uses_table2,
|
||||
Vn_to_locs_table1, Loc_to_vn_table1)
|
||||
;
|
||||
Vn = Next_vn1,
|
||||
Next_vn2 is Next_vn1 + 1,
|
||||
map__set(Lval_to_vn_table1, Vn_lval, Vn,
|
||||
Lval_to_vn_table2),
|
||||
map__set(Rval_to_vn_table1, vn_origlval(Vn_lval), Vn,
|
||||
Rval_to_vn_table2),
|
||||
map__set(Vn_to_rval_table1, Vn, vn_origlval(Vn_lval),
|
||||
Vn_to_rval_table2),
|
||||
map__set(Vn_to_uses_table1, Vn, 1,
|
||||
Vn_to_uses_table2),
|
||||
map__set(Vn_to_locs_table1, Vn, [Vn_lval],
|
||||
Vn_to_locs_table2),
|
||||
map__set(Loc_to_vn_table1, Vn_lval, Vn,
|
||||
Loc_to_vn_table2),
|
||||
Vn_tables = vn_tables(Next_vn2,
|
||||
Lval_to_vn_table2, Rval_to_vn_table2,
|
||||
Vn_to_rval_table2, Vn_to_uses_table2,
|
||||
Vn_to_locs_table2, Loc_to_vn_table2)
|
||||
).
|
||||
|
||||
:- pred value_number__lval_to_vnlval(lval, vn_lval, vn_tables, vn_tables).
|
||||
:- mode value_number__lval_to_vnlval(in, out, di, uo) is det.
|
||||
|
||||
value_number__lval_to_vnlval(reg(Reg), vn_reg(Reg), Vn_tables, Vn_tables).
|
||||
value_number__lval_to_vnlval(succip, vn_succip, Vn_tables, Vn_tables).
|
||||
value_number__lval_to_vnlval(maxfr, vn_maxfr, Vn_tables, Vn_tables).
|
||||
value_number__lval_to_vnlval(curredoip, vn_curredoip, Vn_tables, Vn_tables).
|
||||
value_number__lval_to_vnlval(hp, vn_hp, Vn_tables, Vn_tables).
|
||||
value_number__lval_to_vnlval(sp, vn_sp, Vn_tables, Vn_tables).
|
||||
value_number__lval_to_vnlval(stackvar(Slot), vn_stackvar(Slot),
|
||||
Vn_tables, Vn_tables).
|
||||
value_number__lval_to_vnlval(framevar(Slot), vn_framevar(Slot),
|
||||
Vn_tables, Vn_tables).
|
||||
value_number__lval_to_vnlval(temp(No), vn_temp(No),
|
||||
Vn_tables, Vn_tables).
|
||||
value_number__lval_to_vnlval(field(Tag, Lval, Slot), vn_field(Tag, Vn, Slot),
|
||||
Vn_tables0, Vn_tables) :-
|
||||
value_number__use_lval_find_vn(Lval, Vn, Vn_tables0, Vn_tables).
|
||||
value_number__lval_to_vnlval(lvar(_Var), _, _Vn_tables, _) :-
|
||||
error("Lvar detected in value_number").
|
||||
|
||||
:- pred value_number__flush_lval(vn_lval, vn_tables, vn_tables,
|
||||
int, int, list(instr)).
|
||||
:- mode value_number__flush_lval(in, di, uo, in, out, out) is det.
|
||||
|
||||
% value_number__flush_lval(Vn_lval, Vn_tables0, Vn_tables, Temp0, Temp, Instrs) :-
|
||||
% Vn_tables0 = vn_tables(Next_vn0,
|
||||
% Lval_to_vn_table0, Rval_to_vn_table0,
|
||||
% Vn_to_rval_table0, Vn_to_uses_table0,
|
||||
% Vn_to_locs_table0, Loc_to_vn_table0).
|
||||
% % more to come
|
||||
|
||||
% given a list of root vn_lval/vn pairs, construct a list of vn before vn pairs
|
||||
% do a topological sort, breaking minimal cycles with temp lvals
|
||||
|
||||
Reference in New Issue
Block a user