use STORE ?a instead of PUSH during optimizations

This commit is contained in:
Ulf Norell 2019-04-29 12:03:33 +02:00
parent 690d55eefe
commit 081a4d28b6

View File

@ -195,31 +195,31 @@ resolve_name(#env{ vars = Vars, contract = Contract, locals = Funs }, X) ->
%% -- The compiler -- %% -- The compiler --
to_scode(_Env, {int, N}) -> to_scode(_Env, {int, N}) ->
[aeb_fate_code:push(?i(N))]; [push(?i(N))];
to_scode(_Env, {string, S}) -> to_scode(_Env, {string, S}) ->
[aeb_fate_code:push(?i(aeb_fate_data:make_string(S)))]; [push(?i(aeb_fate_data:make_string(S)))];
to_scode(_Env, {bool, B}) -> to_scode(_Env, {bool, B}) ->
[aeb_fate_code:push(?i(B))]; [push(?i(B))];
to_scode(_Env, {account_pubkey, K}) -> to_scode(_Env, {account_pubkey, K}) ->
[aeb_fate_code:push(?i(aeb_fate_data:make_address(K)))]; [push(?i(aeb_fate_data:make_address(K)))];
to_scode(_Env, {contract_pubkey, K}) -> to_scode(_Env, {contract_pubkey, K}) ->
[aeb_fate_code:push(?i(aeb_fate_data:make_contract(K)))]; [push(?i(aeb_fate_data:make_contract(K)))];
to_scode(_Env, {oracle_pubkey, K}) -> to_scode(_Env, {oracle_pubkey, K}) ->
[aeb_fate_code:push(?i(aeb_fate_data:make_oracle(K)))]; [push(?i(aeb_fate_data:make_oracle(K)))];
to_scode(_Env, {oracle_query_id, K}) -> to_scode(_Env, {oracle_query_id, K}) ->
%% Not actually in FATE yet %% Not actually in FATE yet
[aeb_fate_code:push(?i(aeb_fate_data:make_oracle_query(K)))]; [push(?i(aeb_fate_data:make_oracle_query(K)))];
to_scode(_Env, nil) -> aeb_fate_code:nil(?a); to_scode(_Env, nil) -> aeb_fate_code:nil(?a);
to_scode(Env, {var, X}) -> to_scode(Env, {var, X}) ->
[aeb_fate_code:push(lookup_var(Env, X))]; [push(lookup_var(Env, X))];
to_scode(Env, {con, Ar, I, As}) -> to_scode(Env, {con, Ar, I, As}) ->
N = length(As), N = length(As),
@ -399,6 +399,10 @@ binop_to_scode('::') -> aeb_fate_code:cons(?a, ?a, ?a).
unop_to_scode('!') -> aeb_fate_code:not_op(?a, ?a). unop_to_scode('!') -> aeb_fate_code:not_op(?a, ?a).
%% PUSH and STORE ?a are the same, so we use STORE to make optimizations
%% easier, and specialize to PUSH (which is cheaper) at the end.
push(A) -> aeb_fate_code:store(?a, A).
%% -- Phase II --------------------------------------------------------------- %% -- Phase II ---------------------------------------------------------------
%% Optimize %% Optimize
@ -740,12 +744,12 @@ rules() ->
]. ].
%% Removing pushes that are immediately consumed. %% Removing pushes that are immediately consumed.
r_push_consume({i, Ann1, {'PUSH', A}}, [{i, Ann2, {'POP', B}} | Code]) -> r_push_consume({i, Ann1, {'STORE', ?a, A}}, [{i, Ann2, {'POP', B}} | Code]) ->
case live_out(B, Ann2) of case live_out(B, Ann2) of
true -> {[{i, merge_ann(Ann1, Ann2), {'STORE', B, A}}], Code}; true -> {[{i, merge_ann(Ann1, Ann2), {'STORE', B, A}}], Code};
false -> {[], Code} false -> {[], Code}
end; end;
r_push_consume({i, Ann1, {'PUSH', A}}, [{i, Ann2, I} | Code]) -> r_push_consume({i, Ann1, {'STORE', ?a, A}}, [{i, Ann2, I} | Code]) ->
case op_view(I) of case op_view(I) of
{Op, R, As} -> {Op, R, As} ->
case lists:splitwith(fun(X) -> X /= ?a end, As) of case lists:splitwith(fun(X) -> X /= ?a end, As) of
@ -765,7 +769,7 @@ r_push_consume({i, Ann1, I}, [{i, Ann2, {'STORE', R, ?a}} | Code]) ->
r_push_consume(_, _) -> false. r_push_consume(_, _) -> false.
%% Changing PUSH A, DUPA to PUSH A, PUSH A enables further optimisations %% Changing PUSH A, DUPA to PUSH A, PUSH A enables further optimisations
r_dup_to_push({i, Ann1, Push={'PUSH', _}}, [{i, Ann2, 'DUPA'} | Code]) -> r_dup_to_push({i, Ann1, Push={'STORE', ?a, _}}, [{i, Ann2, 'DUPA'} | Code]) ->
#{ live_in := LiveIn } = Ann1, #{ live_in := LiveIn } = Ann1,
Ann1_ = Ann1#{ live_out => LiveIn }, Ann1_ = Ann1#{ live_out => LiveIn },
Ann2_ = Ann2#{ live_in => LiveIn }, Ann2_ = Ann2#{ live_in => LiveIn },
@ -773,7 +777,7 @@ r_dup_to_push({i, Ann1, Push={'PUSH', _}}, [{i, 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(Push = {i, _, {'PUSH', _}}, [I | Code]) -> r_swap_push(Push = {i, _, {'STORE', ?a, _}}, [I | Code]) ->
case independent(Push, I) of case independent(Push, I) of
true -> true ->
{I1, Push1} = swap_instrs(Push, I), {I1, Push1} = swap_instrs(Push, I),
@ -844,7 +848,6 @@ r_one_shot_var({i, Ann1, I}, [{i, Ann2, J} | Code]) ->
case op_view(I) of case op_view(I) of
{Op, R, As} -> {Op, R, As} ->
Copy = case J of Copy = case J of
{'PUSH', R} -> {write_to, ?a};
{'STORE', S, R} -> {write_to, S}; {'STORE', S, R} -> {write_to, S};
_ -> false _ -> false
end, end,
@ -898,6 +901,7 @@ unannotate({i, _Ann, I}) -> [I].
%% Desugar and specialize %% Desugar and specialize
desugar({'ADD', ?a, ?i(1), ?a}) -> [aeb_fate_code:inc()]; desugar({'ADD', ?a, ?i(1), ?a}) -> [aeb_fate_code:inc()];
desugar({'SUB', ?a, ?a, ?i(1)}) -> [aeb_fate_code:dec()]; desugar({'SUB', ?a, ?a, ?i(1)}) -> [aeb_fate_code:dec()];
desugar({'STORE', ?a, A}) -> [aeb_fate_code:push(A)];
desugar({switch, Arg, Type, Alts, Def}) -> desugar({switch, Arg, Type, Alts, Def}) ->
[{switch, Arg, Type, [desugar(A) || A <- Alts], desugar(Def)}]; [{switch, Arg, Type, [desugar(A) || A <- Alts], desugar(Def)}];
desugar(missing) -> missing; desugar(missing) -> missing;