Handle switch_body in optimizations
This commit is contained in:
parent
ee7bc126fc
commit
b3131504b0
@ -298,7 +298,7 @@ ann_writes([{switch, Type, Alts, Def} | Code], Writes, Acc) ->
|
|||||||
Writes1 = ordsets:union(Writes, ordsets:intersection([WritesDef | WritesAlts])),
|
Writes1 = ordsets:union(Writes, ordsets:intersection([WritesDef | WritesAlts])),
|
||||||
ann_writes(Code, Writes1, [{switch, Type, Alts1, Def1} | Acc]);
|
ann_writes(Code, Writes1, [{switch, Type, Alts1, Def1} | Acc]);
|
||||||
ann_writes([I | Code], Writes, Acc) ->
|
ann_writes([I | Code], Writes, Acc) ->
|
||||||
Ws = var_writes(I),
|
Ws = var_writes({#{}, I}),
|
||||||
Writes1 = ordsets:union(Writes, Ws),
|
Writes1 = ordsets:union(Writes, Ws),
|
||||||
Ann = #{ writes_in => Writes, writes_out => Writes1 },
|
Ann = #{ writes_in => Writes, writes_out => Writes1 },
|
||||||
ann_writes(Code, Writes1, [{Ann, I} | Acc]);
|
ann_writes(Code, Writes1, [{Ann, I} | Acc]);
|
||||||
@ -453,7 +453,7 @@ attributes(I) ->
|
|||||||
'NOP' -> Pure(none, [])
|
'NOP' -> Pure(none, [])
|
||||||
end.
|
end.
|
||||||
|
|
||||||
var_writes(I) ->
|
var_writes({_, I}) ->
|
||||||
#{ write := W } = attributes(I),
|
#{ write := W } = attributes(I),
|
||||||
case W of
|
case W of
|
||||||
{var, _} -> [W];
|
{var, _} -> [W];
|
||||||
@ -464,7 +464,7 @@ independent({switch, _, _, _}, _) -> false;
|
|||||||
independent(_, {switch, _, _, _}) -> false;
|
independent(_, {switch, _, _, _}) -> false;
|
||||||
independent(switch_body, _) -> true;
|
independent(switch_body, _) -> true;
|
||||||
independent(_, switch_body) -> true;
|
independent(_, switch_body) -> true;
|
||||||
independent(I, J) ->
|
independent({_, I}, {_, J}) ->
|
||||||
#{ write := WI, read := RI, pure := PureI } = attributes(I),
|
#{ write := WI, read := RI, pure := PureI } = attributes(I),
|
||||||
#{ write := WJ, read := RJ, pure := PureJ } = attributes(J),
|
#{ write := WJ, read := RJ, pure := PureJ } = attributes(J),
|
||||||
|
|
||||||
@ -484,6 +484,8 @@ merge_ann(#{ live_in := LiveIn }, #{ live_out := LiveOut }) ->
|
|||||||
#{ live_in => LiveIn, live_out => LiveOut }.
|
#{ live_in => LiveIn, live_out => LiveOut }.
|
||||||
|
|
||||||
%% Swap two instructions. Precondition: the instructions are independent/2.
|
%% Swap two instructions. Precondition: the instructions are independent/2.
|
||||||
|
swap_instrs(I, switch_body) -> {switch_body, I};
|
||||||
|
swap_instrs(switch_body, I) -> {I, switch_body};
|
||||||
swap_instrs({#{ live_in := Live1 }, I}, {#{ live_in := Live2, live_out := Live3 }, J}) ->
|
swap_instrs({#{ live_in := Live1 }, I}, {#{ live_in := Live2, live_out := Live3 }, J}) ->
|
||||||
%% Since I and J are independent the J can't read or write anything in
|
%% Since I and J are independent the J can't read or write anything in
|
||||||
%% that I writes.
|
%% that I writes.
|
||||||
@ -573,34 +575,36 @@ r_dup_to_push({Ann1, Push={'PUSH', _}}, [{Ann2, 'DUPA'} | Code]) ->
|
|||||||
r_dup_to_push(_, _) -> false.
|
r_dup_to_push(_, _) -> false.
|
||||||
|
|
||||||
%% Move PUSH A past non-stack instructions.
|
%% Move PUSH A past non-stack instructions.
|
||||||
r_swap_push(PushA = {_, Push = {'PUSH', _}}, [IA = {_, I} | Code]) ->
|
r_swap_push(Push = {_, {'PUSH', _}}, [I | Code]) ->
|
||||||
case independent(Push, I) of
|
case independent(Push, I) of
|
||||||
true ->
|
true ->
|
||||||
{I1, Push1} = swap_instrs(PushA, IA),
|
{I1, Push1} = swap_instrs(Push, I),
|
||||||
{[I1, Push1], Code};
|
{[I1, Push1], Code};
|
||||||
false -> false
|
false -> false
|
||||||
end;
|
end;
|
||||||
r_swap_push(_, _) -> false.
|
r_swap_push(_, _) -> false.
|
||||||
|
|
||||||
%% Match up writes to variables with instructions further down.
|
%% Match up writes to variables with instructions further down.
|
||||||
r_swap_write(IA = {_, I}, [JA = {_, J} | Code]) ->
|
r_swap_write(I = {_, _}, [J | Code]) ->
|
||||||
case {var_writes(I), independent(I, J)} of
|
case {var_writes(I), independent(I, J)} of
|
||||||
{[_], true} ->
|
{[_], true} ->
|
||||||
{J1, I1} = swap_instrs(IA, JA),
|
{J1, I1} = swap_instrs(I, J),
|
||||||
r_swap_write([J1], I1, Code);
|
r_swap_write([J1], I1, Code);
|
||||||
_ -> false
|
_ -> false
|
||||||
end;
|
end;
|
||||||
r_swap_write(_, _) -> false.
|
r_swap_write(_, _) -> false.
|
||||||
|
|
||||||
r_swap_write(Pre, IA = {_, I}, Code0 = [JA | Code]) ->
|
r_swap_write(Pre, I, [switch_body | Code]) ->
|
||||||
case {apply_rules_once(merge_rules(), IA, Code0), JA} of
|
r_swap_write([switch_body | Pre], I, Code);
|
||||||
{{_Rule, New, Rest}, _} ->
|
r_swap_write(Pre, I, Code0 = [J | Code]) ->
|
||||||
|
case apply_rules_once(merge_rules(), I, Code0) of
|
||||||
|
{_Rule, New, Rest} ->
|
||||||
{lists:reverse(Pre) ++ New, Rest};
|
{lists:reverse(Pre) ++ New, Rest};
|
||||||
{false, {_, J}} ->
|
false ->
|
||||||
case independent(I, J) of
|
case independent(I, J) of
|
||||||
false -> false;
|
false -> false;
|
||||||
true ->
|
true ->
|
||||||
{J1, I1} = swap_instrs(IA, JA),
|
{J1, I1} = swap_instrs(I, J),
|
||||||
r_swap_write([J1 | Pre], I1, Code)
|
r_swap_write([J1 | Pre], I1, Code)
|
||||||
end;
|
end;
|
||||||
_ -> false
|
_ -> false
|
||||||
|
Loading…
x
Reference in New Issue
Block a user