2
2
%%% -*- erlang-indent-level: 2 -*-
3
3
%%%-------------------------------------------------------------------
4
%%% File : hipe_ssa_copy_prop.inc
5
%%% Author : Tobias Lindahl <tobiasl@fan.it.uu.se>
6
%%% Description : Copy propagation on ssa form.
4
%%% File : hipe_ssa_copy_prop.inc
5
%%% Author : Tobias Lindahl <tobiasl@it.uu.se>
6
%%% Description : Copy propagation on SSA form.
8
%%% Created : 4 Apr 2003 by Tobias Lindahl <tobiasl@fan.it.uu.se>
8
%%% Created : 4 Apr 2003 by Tobias Lindahl <tobiasl@it.uu.se>
9
9
%%%-------------------------------------------------------------------
13
13
%%--------------------------------------------------------------------
14
%% Two passes through the code choosing the blocks in reverse
14
%% Two passes through the code visiting the blocks in reverse
15
15
%% postorder. The first pass binds all destinations of copying moves
16
%% to the sources and propagates the copies, the second propagates the
17
%% copies and removes the copying moves.
19
%% Copies must not be propagated across the point of redefinition of
20
%% the source variable. If the original value is used after the
21
%% redefinition we must use this value and cannot remove the copying
23
%% %%--------------------------------------------------------------------
16
%% to the sources, and the second propagates the copies and removes
20
%% Since phi-nodes are implemented as instructions they are not
21
%% atomic. If we are not careful we can get the situation (after propagation):
26
%% where the underlined v0 really corresponds to the v0 before the first
30
%% * Find all dependencies between the uses of a
31
%% phi-instruction to the destination of any earlier phi-instruction
32
%% in the same phi-node;
33
%% * Keep the copying move/fmove that defines the variable used in the
34
%% latter phi-instruction; and
35
%% * Do not propagate the copy into the phi-instruction
37
%%--------------------------------------------------------------------
26
40
Labels = ?cfg:reverse_postorder(Cfg),
27
{Info, NewCfg1} = propagate(Labels, Cfg, gb_trees:empty(), fun first_pass/3),
28
{_, NewCfg2} = propagate(Labels, NewCfg1, Info, fun second_pass/3),
41
{Info,PhiDep} = analyse(Labels, Cfg, gb_trees:empty(), gb_sets:empty()),
42
rewrite(Labels, Cfg, Info, PhiDep).
31
propagate([Label|Left], Cfg, Info, Fun)->
44
analyse([Label|Left], Cfg, Info, PhiDep) ->
32
45
BB = ?cfg:bb(Cfg, Label),
33
46
Code = hipe_bb:code(BB),
34
{NewInfo, NewCode} = Fun(Code, Info, []),
35
NewBB = hipe_bb:code_update(BB, NewCode),
36
propagate(Left, ?cfg:bb_update(Cfg, Label, NewBB), NewInfo, Fun);
37
propagate([], Cfg, Info, _Fun) ->
40
first_pass([I|Left], Info, Acc)->
43
NewInfo = get_info_mov_or_fmov(I, Info),
44
first_pass(Left, NewInfo, [I|Acc]);
46
NewInfo = get_info_mov_or_fmov(I, Info),
47
first_pass(Left, NewInfo, [I|Acc]);
49
{_, NewI} = propagate_instr(I, Info),
50
first_pass(Left, Info, [NewI|Acc])
52
first_pass([], Info, Acc) ->
53
{Info, lists:reverse(Acc)}.
55
get_info_mov_or_fmov(I, Info)->
47
NewPhiDep = get_phi_dep(Code, gb_sets:empty(), PhiDep),
48
NewInfo = analyse_code(Code, Info),
49
analyse(Left, Cfg, NewInfo, NewPhiDep);
50
analyse([], _Cfg, Info, PhiDep) ->
53
get_phi_dep([I|Left], Defined, Dep) ->
57
[Def] = ?code:defines(I),
58
NewDep = add_dep(Use, Defined, Dep),
59
get_phi_dep(Left, gb_sets:insert(Def, Defined), NewDep);
63
get_phi_dep([], _Defined, Dep) ->
66
add_dep([Use|Left], Defined, Dep) ->
67
case gb_trees:lookup(Use, Dep) of
69
add_dep(Left, Defined, gb_trees:insert(Use, Defined, Dep));
71
NewSet = gb_sets:union(Defined, Set),
72
add_dep(Left, Defined, gb_trees:enter(Use, NewSet, Dep))
74
add_dep([], _Defined, Dep) ->
77
has_dep(Use, Def, Dep) ->
78
case gb_trees:lookup(Use, Dep) of
82
gb_sets:is_member(Def, Set)
85
analyse_code([I|Left], Info) ->
88
NewInfo = get_info_move_or_fmove(I, Info),
89
analyse_code(Left, NewInfo);
91
NewInfo = get_info_move_or_fmove(I, Info),
92
analyse_code(Left, NewInfo);
94
analyse_code(Left, Info)
96
analyse_code([], Info) ->
99
get_info_move_or_fmove(I, Info) ->
56
100
case ?code:uses(I) of
57
101
[] -> %% Constant.
60
104
add_binding(?code:defines(I), Src, Info)
63
second_pass([I|Left], Info, Acc)->
66
NewI = propagate_mov_or_fmov(I, Info),
67
second_pass(Left, Info, NewI++Acc);
69
NewI = propagate_mov_or_fmov(I, Info),
70
second_pass(Left, Info, NewI++Acc);
107
rewrite([Label|Left], Cfg, Info, PhiDep) ->
108
BB = ?cfg:bb(Cfg, Label),
109
Code = hipe_bb:code(BB),
110
NewCode = rewrite_code(Code, Info, PhiDep, []),
111
NewBB = hipe_bb:code_update(BB, NewCode),
112
rewrite(Left, ?cfg:bb_add(Cfg, Label, NewBB), Info, PhiDep);
113
rewrite([], Cfg, _Info, _PhiDep) ->
116
rewrite_code([I|Left], Info, PhiDep, Acc) ->
119
Fun = fun(X, Y) -> ?code:mk_move(X, Y)end,
120
NewI = rewrite_move_or_fmove(I, Fun, Info, PhiDep),
121
rewrite_code(Left, Info, PhiDep, NewI++Acc);
123
Fun = fun(X, Y) -> ?code:mk_fmove(X, Y)end,
124
NewI = rewrite_move_or_fmove(I, Fun, Info, PhiDep),
125
rewrite_code(Left, Info, PhiDep, NewI++Acc);
72
{NewInfo1, NewI} = propagate_instr(I, Info),
73
NewInfo2 = add_binding(?code:defines(I), 'redefined', NewInfo1),
74
second_pass(Left, NewInfo2, [NewI|Acc])
127
NewI = rewrite_instr(I, Info, PhiDep),
128
rewrite_code(Left, Info, PhiDep, [NewI|Acc])
76
second_pass([], Info, Acc) ->
77
{Info, lists:reverse(Acc)}.
130
rewrite_code([], _Info, _PhiDep, Acc) ->
79
propagate_mov_or_fmov(I, Info)->
133
rewrite_move_or_fmove(I, Fun, Info, PhiDep) ->
80
134
case ?code:uses(I) of
135
[] ->%% Constant move. Keep it!
84
case gb_trees:lookup(hd(?code:defines(I)), Info) of
85
none -> %% We must keep this instruction.
138
Dst = hd(?code:defines(I)),
139
case gb_trees:lookup(Dst, Info) of
141
case has_dep(Dst, Root, PhiDep) of
142
true -> %% Must keep the copying move!
92
propagate_instr(I, Info)->
93
propagate_instr0(I, ?code:uses(I), Info, []).
95
propagate_instr0(I, [Key|Left], Info, UpdateInfo)->
153
rewrite_instr(I, Info, PhiDep) ->
154
rewrite_instr0(I, ?code:uses(I), Info, PhiDep, []).
156
rewrite_instr0(I, [Key|Left], Info, PhiDep, UpdateInfo) ->
96
157
case gb_trees:lookup(Key, Info) of
97
{value, 'redefined'} ->
98
propagate_instr0(I, Left, Info, UpdateInfo);
100
case gb_trees:lookup(Val, Info) of
101
{value, 'redefined'} ->
102
%%Remove the binding to show that the copying move cannot be removed.
103
propagate_instr0(I, Left, gb_trees:delete(Key, Info), UpdateInfo);
159
rewrite_instr0(I, Left, Info, PhiDep, UpdateInfo);
161
case gb_trees:lookup(Key, Info) of
163
case has_dep(Key, Root, PhiDep) of
164
true -> %% Must keep Key!
165
rewrite_instr0(I, Left, Info, PhiDep, UpdateInfo);
167
rewrite_instr0(I, Left, Info, PhiDep, [{Key, Root}|UpdateInfo])
105
propagate_instr0(I, Left, Info, [{Key, Val}|UpdateInfo])
108
propagate_instr0(I, Left, Info, UpdateInfo)
170
rewrite_instr0(I, Left, Info, PhiDep, UpdateInfo)
110
propagate_instr0(I, [], Info, UpdateInfo)->
111
{Info, ?code:subst(UpdateInfo, I)}.
173
rewrite_instr0(I, [], _Info, _PhiDep, UpdateInfo) ->
174
?code:subst(UpdateInfo, I).
113
add_binding([Key|Left], Val, Info)->
176
add_binding([Key|Left], Val, Info) ->
114
177
%% Make sure the key is bound to the end of any copy-chains.
116
179
case gb_trees:lookup(Val, Info) of