Fate compiler #553

Merged
zxq9 merged 87 commits from fate-compiler into master 2019-05-07 22:48:47 +09:00
Showing only changes of commit 4814cfbf96 - Show all commits

View File

@ -415,13 +415,19 @@ independent(I, J) ->
merge_ann(#{ live_in := LiveIn }, #{ live_out := LiveOut }) -> merge_ann(#{ live_in := LiveIn }, #{ live_out := LiveOut }) ->
#{ live_in => LiveIn, live_out => LiveOut }. #{ live_in => LiveIn, live_out => LiveOut }.
%% When swapping two instructions %% Swap two instructions. Precondition: the instructions are independent/2.
swap_ann(#{ live_in := Live1, live_out := Live2 }, #{ live_in := Live2, live_out := Live3 }) -> swap_instrs({#{ live_in := Live1, live_out := Live2 }, I}, {#{ live_in := Live2, live_out := Live3 }, J}) ->
Live2_ = ordsets:union([Live1, Live2, Live3]), %% Conservative approximation %% Since I and J are independent the J can't read or write anything in
{#{ live_in => Live1, live_out => Live2_ }, %% that I writes.
#{ live_in => Live2_, live_out => Live3 }}. WritesI = ordsets:subtract(Live2, Live1),
%% Any final reads by J, that I does not read should be removed from Live2.
#{ read := ReadsI } = attributes(I),
ReadsJ = ordsets:subtract(Live2, ordsets:union(Live3, ReadsI)),
Live2_ = ordsets:subtract(ordsets:union([Live1, Live2, Live3]), ordsets:union(WritesI, ReadsJ)),
{{#{ live_in => Live1, live_out => Live2_ }, J},
{#{ live_in => Live2_, live_out => Live3 }, I}}.
%% live_in(R, #{ live_in := LiveIn }) -> ordsets:is_element(R, LiveIn). live_in(R, #{ live_in := LiveIn }) -> ordsets:is_element(R, LiveIn).
live_out(R, #{ live_out := LiveOut }) -> ordsets:is_element(R, LiveOut). live_out(R, #{ live_out := LiveOut }) -> ordsets:is_element(R, LiveOut).
%% -- Optimizations -- %% -- Optimizations --
@ -442,7 +448,7 @@ apply_rules(Rules, I, Code, Options) ->
case apply_rules_once(Rules, I, Code) of case apply_rules_once(Rules, I, Code) of
false -> [I | Code]; false -> [I | Code];
{RName, New, Rest} -> {RName, New, Rest} ->
debug(opt_rules, Options, "Applied ~p:\n~s ==>\n~s", [RName, pp_ann(" ", [I | Code]), pp_ann(" ", New ++ Rest)]), debug(opt_rules, Options, " Applied ~p:\n~s ==>\n~s\n", [RName, pp_ann(" ", [I | Code]), pp_ann(" ", New ++ Rest)]),
lists:foldr(Cons, Rest, New) lists:foldr(Cons, Rest, New)
end. end.
@ -497,34 +503,35 @@ 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({Ann1, Push = {'PUSH', _}}, [{Ann2, I} | Code]) -> r_swap_push(PushA = {_, Push = {'PUSH', _}}, [IA = {_, I} | Code]) ->
case independent(Push, I) of case independent(Push, I) of
true -> true ->
{Ann1_, Ann2_} = swap_ann(Ann1, Ann2), {I1, Push1} = swap_instrs(PushA, IA),
{[{Ann1_, I}, {Ann2_, Push}], 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({AnnI, I}, [{AnnJ, J} | Code]) -> r_swap_write(IA = {_, I}, [JA = {_, J} | Code]) ->
case {var_writes(I), independent(I, J)} of case {var_writes(I), independent(I, J)} of
{[_], true} -> {[_], true} ->
{AnnJ_, AnnI_} = swap_ann(AnnI, AnnJ), {J1, I1} = swap_instrs(IA, JA),
r_swap_write([{AnnJ_, J}], {AnnI_, I}, Code); r_swap_write([J1], I1, Code);
_ -> false _ -> false
end; end;
r_swap_write(_, _) -> false. r_swap_write(_, _) -> false.
r_swap_write(Pre, {AnnI, I}, Code0 = [{AnnJ, J} | Code]) -> r_swap_write(Pre, IA = {_, I}, Code0 = [JA = {_, J} | Code]) ->
case apply_rules_once(merge_rules(), {AnnI, I}, Code0) of case apply_rules_once(merge_rules(), IA, Code0) of
{_, New, Rest} -> {lists:reverse(Pre) ++ New, Rest}; {_Rule, New, Rest} ->
{lists:reverse(Pre) ++ New, Rest};
false -> false ->
case independent(I, J) of case independent(I, J) of
false -> false; false -> false;
true -> true ->
{AnnJ_, AnnI_} = swap_ann(AnnI, AnnJ), {J1, I1} = swap_instrs(IA, JA),
r_swap_write([{AnnJ_, J} | Pre], {AnnI_, I}, Code) r_swap_write([J1 | Pre], I1, Code)
end end
end; end;
r_swap_write(_, _, []) -> false. r_swap_write(_, _, []) -> false.