Get rid of unnecessary STORE instructions

This commit is contained in:
Ulf Norell 2019-04-05 10:50:47 +02:00
parent 4b6191aa25
commit d05130a569

View File

@ -466,7 +466,8 @@ rules() ->
merge_rules() ++ merge_rules() ++
[?RULE(r_dup_to_push), [?RULE(r_dup_to_push),
?RULE(r_swap_push), ?RULE(r_swap_push),
?RULE(r_swap_write) ?RULE(r_swap_write),
?RULE(r_inline)
]. ].
%% Removing pushes that are immediately consumed. %% Removing pushes that are immediately consumed.
@ -528,6 +529,30 @@ r_swap_write(Pre, {AnnI, I}, Code0 = [{AnnJ, J} | Code]) ->
end; end;
r_swap_write(_, _, []) -> false. r_swap_write(_, _, []) -> false.
%% Inline stores
r_inline(I = {_, {'STORE', R = {var, _}, A = {arg, _}}}, Code) ->
%% Not when A is var unless updating the annotations properly.
r_inline([I], R, A, Code);
r_inline(_, _) -> false.
r_inline(Acc, R, A, [{Ann, I} | Code]) ->
#{ write := W, pure := Pure } = attributes(I),
Inl = fun(X) when X == R -> A; (X) -> X end,
case not live_in(R, Ann) orelse not Pure orelse lists:member(W, [R, A]) of
true -> false;
false ->
case I of
{Op, S, B, C} when ?IsBinOp(Op), B == R orelse C == R ->
Acc1 = [{Ann, {Op, S, Inl(B), Inl(C)}} | Acc],
case r_inline(Acc1, R, A, Code) of
false -> {lists:reverse(Acc1), Code};
{New, Rest} -> {New, Rest}
end;
_ -> r_inline([{Ann, I} | Acc], R, A, Code)
end
end;
r_inline(_Acc, _, _, []) -> false.
%% Shortcut write followed by final read %% Shortcut write followed by final read
r_one_shot_var({Ann1, {Op, R = {var, _}, A, B}}, [{Ann2, J} | Code]) when ?IsBinOp(Op) -> r_one_shot_var({Ann1, {Op, R = {var, _}, A, B}}, [{Ann2, J} | Code]) when ?IsBinOp(Op) ->
Copy = case J of Copy = case J of
@ -552,6 +577,16 @@ r_write_to_dead_var({Ann, {Op, R = {var, _}, A, B}}, Code) when ?IsBinOp(Op) ->
{[{Ann, {'POP', R}} || X <- [A, B], X == ?a], Code}; {[{Ann, {'POP', R}} || X <- [A, B], X == ?a], Code};
true -> false true -> false
end; end;
r_write_to_dead_var({Ann, {'STORE', R = {var, _}, A}}, Code) when A /= ?a ->
case live_out(R, Ann) of
false ->
case Code of
[] -> {[], []};
[{Ann1, I} | Code1] ->
{[], [{merge_ann(Ann, Ann1), I} | Code1]}
end;
true -> false
end;
r_write_to_dead_var(_, _) -> false. r_write_to_dead_var(_, _) -> false.