Files
mercury/compiler/dupelim.m
Zoltan Somogyi cac7d6a246 Fix allocation to work properly for --args compact.
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.
1996-05-29 10:56:45 +00:00

294 lines
12 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.
%-----------------------------------------------------------------------------%
% dupelim.m - eliminate some duplicate code sequences.
% Author: zs.
%-----------------------------------------------------------------------------%
:- module dupelim.
:- interface.
:- import_module list, llds.
:- pred dupelim__main(list(instruction), list(instruction)).
% :- mode dupelim__main(di, uo) is det.
:- mode dupelim__main(in, out) is det.
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module bool, std_util, map, require.
:- import_module opt_util.
:- type block == pair(label, list(instruction)).
dupelim__main(Instrs0, Instrs) :-
map__init(Seqmap0),
map__init(Replmap0),
opt_util__skip_to_next_label(Instrs0, Initial, Instrs1),
dupelim__make_blocks(Instrs1, Blocks0),
dupelim__build_maps(Blocks0, yes, Seqmap0, Replmap0, Replmap),
dupelim__replace_labels(Blocks0, Replmap, Blocks1),
dupelim__condense(Blocks1, Instrs2),
list__append(Initial, Instrs2, Instrs).
%-----------------------------------------------------------------------------%
:- pred dupelim__make_blocks(list(instruction), list(block)).
:- mode dupelim__make_blocks(in, out) is det.
dupelim__make_blocks(Instrs0, Blocks) :-
( Instrs0 = [] ->
Blocks = []
; Instrs0 = [label(BlockLabel) - _ | Instrs1] ->
opt_util__skip_to_next_label(Instrs1, BlockCode, Instrs2),
dupelim__make_blocks(Instrs2, Blocks1),
Blocks = [BlockLabel - BlockCode | Blocks1]
;
error("instruction other than label in dupelim__make_blocks")
).
%-----------------------------------------------------------------------------%
:- pred dupelim__build_maps(list(block), bool, map(list(instruction), label),
map(label, label), map(label, label)).
% :- mode dupelim__build_maps(ui, in, in, di, uo) is det.
:- mode dupelim__build_maps(in, in, in, in, out) is det.
% If a block can fall through, it should not be put into the sequence map.
% Two identical blocks that both fall through will fall through into
% different blocks.
% If a block can be fallen into, its label may not be replaced, since that
% would require the introduction of a goto to the new label at the end of
% the previous block.
dupelim__build_maps([], _FallInto, _Seqmap, Replmap, Replmap).
dupelim__build_maps([Label - Code | Blocks1], FallInto, Seqmap0,
Replmap0, Replmap) :-
(
list__reverse(Code, RevCode0),
opt_util__skip_comments_livevals(RevCode0, RevCode1),
RevCode1 = [Uinstr - _ | _],
opt_util__can_instr_fall_through(Uinstr, no)
->
FallThrough = no
;
FallThrough = yes
),
( map__search(Seqmap0, Code, OldLabel) ->
Seqmap1 = Seqmap0,
(
FallInto = yes,
Replmap1 = Replmap0
;
FallInto = no,
map__det_insert(Replmap0, Label, OldLabel, Replmap1)
)
;
Replmap1 = Replmap0,
(
FallThrough = yes,
Seqmap1 = Seqmap0
;
FallThrough = no,
map__det_insert(Seqmap0, Code, Label, Seqmap1)
)
),
dupelim__build_maps(Blocks1, FallThrough, Seqmap1, Replmap1, Replmap).
%-----------------------------------------------------------------------------%
:- pred dupelim__replace_labels(list(block), map(label, label), list(block)).
% :- mode dupelim__replace_labels(di, in, uo) is det.
:- mode dupelim__replace_labels(in, in, out) is det.
dupelim__replace_labels([], _Replmap, []).
dupelim__replace_labels([Label - Code | Blocks1], Replmap, Blocks) :-
( map__search(Replmap, Label, _) ->
dupelim__replace_labels(Blocks1, Replmap, Blocks)
;
dupelim__replace_labels_instr_list(Code, Replmap, Code1),
dupelim__replace_labels(Blocks1, Replmap, Blocks2),
Blocks = [Label - Code1 | Blocks2]
).
:- pred dupelim__replace_labels_instr_list(list(instruction), map(label, label),
list(instruction)).
% :- mode dupelim__replace_labels_instr_list(di, in, uo) is det.
:- mode dupelim__replace_labels_instr_list(in, in, out) is det.
dupelim__replace_labels_instr_list([], _Replmap, []).
dupelim__replace_labels_instr_list([Instr0 - Comment | Instrs0],
Replmap, [Instr - Comment | Instrs]) :-
dupelim__replace_labels_instr(Instr0, Replmap, Instr),
dupelim__replace_labels_instr_list(Instrs0, Replmap, Instrs).
:- pred dupelim__replace_labels_instr(instr, map(label, label), instr).
% :- mode dupelim__replace_labels_instr(di, in, uo) is det.
:- mode dupelim__replace_labels_instr(in, in, out) is det.
dupelim__replace_labels_instr(comment(Comment), _, comment(Comment)).
dupelim__replace_labels_instr(livevals(Livevals), _, livevals(Livevals)).
dupelim__replace_labels_instr(block(R, F, Instrs0), Replmap,
block(R, F, Instrs)) :-
dupelim__replace_labels_instr_list(Instrs0, Replmap, Instrs).
dupelim__replace_labels_instr(assign(Lval0, Rval0), Replmap,
assign(Lval, Rval)) :-
dupelim__replace_labels_lval(Lval0, Replmap, Lval),
dupelim__replace_labels_rval(Rval0, Replmap, Rval).
dupelim__replace_labels_instr(call(Target, Return0, LiveInfo, CM),
Replmap, call(Target, Return, LiveInfo, CM)) :-
dupelim__replace_labels_code_addr(Return0, Replmap, Return).
dupelim__replace_labels_instr(mkframe(Name, Size, Redoip0), Replmap,
mkframe(Name, Size, Redoip)) :-
dupelim__replace_labels_code_addr(Redoip0, Replmap, Redoip).
dupelim__replace_labels_instr(modframe(Redoip0), Replmap, modframe(Redoip)) :-
dupelim__replace_labels_code_addr(Redoip0, Replmap, Redoip).
dupelim__replace_labels_instr(label(_), _, _) :-
error("found label in dupelim__replace_labels_instr").
dupelim__replace_labels_instr(goto(Target0), Replmap, goto(Target)) :-
dupelim__replace_labels_code_addr(Target0, Replmap, Target).
dupelim__replace_labels_instr(computed_goto(Rval0, Labels0), Replmap,
computed_goto(Rval, Labels)) :-
dupelim__replace_labels_rval(Rval0, Replmap, Rval),
dupelim__replace_labels_label_list(Labels0, Replmap, Labels).
dupelim__replace_labels_instr(c_code(Code), _, c_code(Code)).
dupelim__replace_labels_instr(if_val(Rval0, Target0), Replmap,
if_val(Rval, Target)) :-
dupelim__replace_labels_rval(Rval0, Replmap, Rval),
dupelim__replace_labels_code_addr(Target0, Replmap, Target).
dupelim__replace_labels_instr(incr_hp(Lval0, MaybeTag, Rval0), Replmap,
incr_hp(Lval, MaybeTag, Rval)) :-
dupelim__replace_labels_lval(Lval0, Replmap, Lval),
dupelim__replace_labels_rval(Rval0, Replmap, Rval).
dupelim__replace_labels_instr(mark_hp(Lval0), Replmap, mark_hp(Lval)) :-
dupelim__replace_labels_lval(Lval0, Replmap, Lval).
dupelim__replace_labels_instr(restore_hp(Rval0), Replmap, restore_hp(Rval)) :-
dupelim__replace_labels_rval(Rval0, Replmap, Rval).
dupelim__replace_labels_instr(store_ticket(Lval0), Replmap,
store_ticket(Lval)) :-
dupelim__replace_labels_lval(Lval0, Replmap, Lval).
dupelim__replace_labels_instr(restore_ticket(Rval0), Replmap,
restore_ticket(Rval)) :-
dupelim__replace_labels_rval(Rval0, Replmap, Rval).
dupelim__replace_labels_instr(discard_ticket, _, discard_ticket).
dupelim__replace_labels_instr(incr_sp(Size), _, incr_sp(Size)).
dupelim__replace_labels_instr(decr_sp(Size), _, decr_sp(Size)).
dupelim__replace_labels_instr(pragma_c(A,B,C,D), _, pragma_c(A,B,C,D)).
:- pred dupelim__replace_labels_lval(lval, map(label, label), lval).
% :- mode dupelim__replace_labels_lval(di, in, uo) is det.
:- mode dupelim__replace_labels_lval(in, in, out) is det.
dupelim__replace_labels_lval(reg(Reg), _, reg(Reg)).
dupelim__replace_labels_lval(stackvar(N), _, stackvar(N)).
dupelim__replace_labels_lval(framevar(N), _, framevar(N)).
dupelim__replace_labels_lval(succip, _, succip).
dupelim__replace_labels_lval(maxfr, _, maxfr).
dupelim__replace_labels_lval(curfr, _, curfr).
dupelim__replace_labels_lval(succip(Rval0), Replmap, succip(Rval)) :-
dupelim__replace_labels_rval(Rval0, Replmap, Rval).
dupelim__replace_labels_lval(redoip(Rval0), Replmap, redoip(Rval)) :-
dupelim__replace_labels_rval(Rval0, Replmap, Rval).
dupelim__replace_labels_lval(succfr(Rval0), Replmap, succfr(Rval)) :-
dupelim__replace_labels_rval(Rval0, Replmap, Rval).
dupelim__replace_labels_lval(prevfr(Rval0), Replmap, prevfr(Rval)) :-
dupelim__replace_labels_rval(Rval0, Replmap, Rval).
dupelim__replace_labels_lval(hp, _, hp).
dupelim__replace_labels_lval(sp, _, sp).
dupelim__replace_labels_lval(field(Tag, Base0, Offset0), Replmap,
field(Tag, Base, Offset)) :-
dupelim__replace_labels_rval(Base0, Replmap, Base),
dupelim__replace_labels_rval(Offset0, Replmap, Offset).
dupelim__replace_labels_lval(lvar(Var), _, lvar(Var)).
dupelim__replace_labels_lval(temp(N), _, temp(N)).
:- pred dupelim__replace_labels_rval(rval, map(label, label), rval).
% :- mode dupelim__replace_labels_rval(di, in, uo) is det.
:- mode dupelim__replace_labels_rval(in, in, out) is det.
dupelim__replace_labels_rval(lval(Lval0), Replmap, lval(Lval)) :-
dupelim__replace_labels_lval(Lval0, Replmap, Lval).
dupelim__replace_labels_rval(var(Var), _, var(Var)).
dupelim__replace_labels_rval(create(Tag, Rvals, N), _, create(Tag, Rvals, N)).
dupelim__replace_labels_rval(mkword(Tag, Rval0), Replmap, mkword(Tag, Rval)) :-
dupelim__replace_labels_rval(Rval0, Replmap, Rval).
dupelim__replace_labels_rval(const(Const0), Replmap, const(Const)) :-
dupelim__replace_labels_rval_const(Const0, Replmap, Const).
dupelim__replace_labels_rval(unop(Op, Rval0), Replmap, unop(Op, Rval)) :-
dupelim__replace_labels_rval(Rval0, Replmap, Rval).
dupelim__replace_labels_rval(binop(Op, LRval0, RRval0), Replmap,
binop(Op, LRval, RRval)) :-
dupelim__replace_labels_rval(LRval0, Replmap, LRval),
dupelim__replace_labels_rval(RRval0, Replmap, RRval).
:- pred dupelim__replace_labels_rval_const(rval_const, map(label, label),
rval_const).
% :- mode dupelim__replace_labels_rval_const(di, in, uo) is det.
:- mode dupelim__replace_labels_rval_const(in, in, out) is det.
dupelim__replace_labels_rval_const(true, _, true).
dupelim__replace_labels_rval_const(false, _, false).
dupelim__replace_labels_rval_const(int_const(N), _, int_const(N)).
dupelim__replace_labels_rval_const(float_const(N), _, float_const(N)).
dupelim__replace_labels_rval_const(string_const(S), _, string_const(S)).
dupelim__replace_labels_rval_const(address_const(Addr0), Replmap,
address_const(Addr)) :-
dupelim__replace_labels_code_addr(Addr0, Replmap, Addr).
:- pred dupelim__replace_labels_code_addr(code_addr, map(label, label),
code_addr).
% :- mode dupelim__replace_labels_code_addr(di, in, uo) is det.
:- mode dupelim__replace_labels_code_addr(in, in, out) is det.
dupelim__replace_labels_code_addr(label(Label0), Replmap, label(Label)) :-
dupelim__replace_labels_label(Label0, Replmap, Label).
dupelim__replace_labels_code_addr(imported(Proc), _, imported(Proc)).
dupelim__replace_labels_code_addr(succip, _, succip).
dupelim__replace_labels_code_addr(do_succeed(Last), _, do_succeed(Last)).
dupelim__replace_labels_code_addr(do_redo, _, do_redo).
dupelim__replace_labels_code_addr(do_fail, _, do_fail).
dupelim__replace_labels_code_addr(do_det_closure, _, do_det_closure).
dupelim__replace_labels_code_addr(do_semidet_closure, _, do_semidet_closure).
dupelim__replace_labels_code_addr(do_nondet_closure, _, do_nondet_closure).
:- pred dupelim__replace_labels_label_list(list(label), map(label, label),
list(label)).
% :- mode dupelim__replace_labels_label_list(di, in, uo) is det.
:- mode dupelim__replace_labels_label_list(in, in, out) is det.
dupelim__replace_labels_label_list([], _Replmap, []).
dupelim__replace_labels_label_list([Label0 | Labels0], Replmap,
[Label | Labels]) :-
dupelim__replace_labels_label(Label0, Replmap, Label),
dupelim__replace_labels_label_list(Labels0, Replmap, Labels).
:- pred dupelim__replace_labels_label(label, map(label, label), label).
% :- mode dupelim__replace_labels_label(di, in, uo) is det.
:- mode dupelim__replace_labels_label(in, in, out) is det.
dupelim__replace_labels_label(Label0, Replmap, Label) :-
( map__search(Replmap, Label0, NewLabel) ->
Label = NewLabel
;
Label = Label0
).
:- pred dupelim__condense(list(block), list(instruction)).
% :- mode dupelim__condense(di, uo) is det.
:- mode dupelim__condense(in, out) is det.
dupelim__condense([], []).
dupelim__condense([Label - Code | Blocks1], Instrs) :-
dupelim__condense(Blocks1, Instrs1),
list__append([label(Label) - "" | Code], Instrs1, Instrs).