1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
%-----------------------------------------------------------------------------%
% Copyright (C) 1994-1999 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%
% labelopt.m - module to eliminate useless labels and dead code.
% Author: zs.
%-----------------------------------------------------------------------------%
:- module labelopt.
:- interface.
:- import_module bool, list, set.
:- import_module llds.
% Build up a set showing which labels are branched to,
% then traverse the instruction list removing unnecessary labels.
% If the instruction before the label branches away, we also
% remove the instruction block following the label.
:- pred labelopt_main(list(instruction)::in, bool::in, set(label)::in,
list(instruction)::out, bool::out) is det.
% Build up a set showing which labels are referred to.
% The input set is the list of labels referred to from outside
% the given list of instructions.
:- pred labelopt__build_useset(list(instruction)::in, set(label)::in,
set(label)::out) is det.
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module opt_util.
:- import_module std_util.
labelopt_main(Instrs0, Final, LayoutLabelSet, Instrs, Mod) :-
labelopt__build_useset(Instrs0, LayoutLabelSet, Useset),
labelopt__instr_list(Instrs0, yes, Useset, Instrs1, Mod),
( Final = yes, Mod = yes ->
labelopt_main(Instrs1, Final, LayoutLabelSet, Instrs, _)
;
Instrs = Instrs1
).
%-----------------------------------------------------------------------------%
labelopt__build_useset([], Useset, Useset).
labelopt__build_useset([Instr | Instructions], Useset0, Useset) :-
Instr = Uinstr - _Comment,
opt_util__instr_labels(Uinstr, Labels, _CodeAddresses),
set__insert_list(Useset0, Labels, Useset1),
labelopt__build_useset(Instructions, Useset1, Useset).
%-----------------------------------------------------------------------------%
% Go through the given instruction sequence. When we find a label,
% we check whether the label can be branched to either from within
% the procedure or from the outside. If yes, we leave it alone.
% If not, we delete it. We delete the following code as well if
% the label was preceded by code that cannot fall through.
:- pred labelopt__instr_list(list(instruction)::in, bool::in, set(label)::in,
list(instruction)::out, bool::out) is det.
labelopt__instr_list([], _Fallthrough, _Useset, [], no).
labelopt__instr_list([Instr0 | MoreInstrs0],
Fallthrough, Useset, MoreInstrs, Mod) :-
Instr0 = Uinstr0 - _Comment,
( Uinstr0 = label(Label) ->
(
( Label = exported(_)
; Label = local(_)
; set__member(Label, Useset)
)
->
ReplInstrs = [Instr0],
Fallthrough1 = yes,
Mod0 = no
;
labelopt__eliminate(Instr0, yes(Fallthrough),
ReplInstrs, Mod0),
Fallthrough1 = Fallthrough
)
;
( Fallthrough = yes ->
ReplInstrs = [Instr0],
Mod0 = no
;
labelopt__eliminate(Instr0, no, ReplInstrs, Mod0)
),
opt_util__can_instr_fall_through(Uinstr0, Canfallthrough),
( Canfallthrough = yes ->
Fallthrough1 = Fallthrough
;
Fallthrough1 = no
)
),
labelopt__instr_list(MoreInstrs0, Fallthrough1, Useset,
MoreInstrs1, Mod1),
list__append(ReplInstrs, MoreInstrs1, MoreInstrs),
( Mod0 = no, Mod1 = no ->
Mod = no
;
Mod = yes
).
% Instead of removing eliminated instructions from the instruction list,
% we can replace them by placeholder comments. The original comment
% field on the instruction is often enough to deduce what the
% eliminated instruction was.
:- pred labelopt__eliminate(instruction::in, maybe(bool)::in,
list(instruction)::out, bool::out) is det.
labelopt__eliminate(Uinstr0 - Comment0, Label, Instr, Mod) :-
labelopt_eliminate_total(Total),
(
Total = yes,
Instr = [],
Mod = yes
;
Total = no,
( Uinstr0 = comment(_) ->
Comment = Comment0,
Uinstr = Uinstr0,
Mod = no
;
( Label = yes(Follow) ->
( Follow = yes ->
Uinstr = comment("eliminated label only")
;
% Follow = no,
Uinstr = comment("eliminated label and block")
)
;
% Label = no,
Uinstr = comment("eliminated instruction")
),
Comment = Comment0,
Mod = yes
),
Instr = [Uinstr - Comment]
).
:- pred labelopt_eliminate_total(bool::out) is det.
labelopt_eliminate_total(yes).
%-----------------------------------------------------------------------------%
|