From 0409a658b082edae674c879804af0f036e126aa6 Mon Sep 17 00:00:00 2001 From: Ulf Norell Date: Tue, 28 May 2019 11:45:32 +0200 Subject: [PATCH] Update to new TUPLE instruction ... and minor fixes --- rebar.config | 3 +-- rebar.lock | 2 +- src/aeso_fcode_to_fate.erl | 35 ++++++++++++----------------------- 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/rebar.config b/rebar.config index fdc3531..d7c001d 100644 --- a/rebar.config +++ b/rebar.config @@ -2,8 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", - {ref, "241a96e"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "f129887"}}} , {getopt, "1.0.1"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index 29a26f8..037273d 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.1.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"241a96ebaa3e041781003cd20532a59ace87eb87"}}, + {ref,"f1298870e526f4e9330447d3a281af5ef4e06e17"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 75e0032..e90a1c7 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -159,7 +159,7 @@ add_default_init_function(SFuns, {tuple, []}) -> SFuns; error -> Sig = {[], {tuple, []}}, - Body = [aeb_fate_ops:tuple(0)], + Body = [tuple(0)], SFuns#{ InitName => {Sig, Body} } end. @@ -221,7 +221,7 @@ to_scode(Env, {con, Ar, I, As}) -> to_scode(Env, {tuple, As}) -> N = length(As), [[ to_scode(notail(Env), A) || A <- As ], - aeb_fate_ops:tuple(N)]; + tuple(N)]; to_scode(Env, {proj, E, I}) -> [to_scode(notail(Env), E), @@ -396,7 +396,7 @@ builtin_to_scode(_Env, get_state, []) -> [push(?s)]; builtin_to_scode(Env, set_state, [_] = Args) -> call_to_scode(Env, [aeb_fate_ops:store(?s, ?a), - aeb_fate_ops:tuple(0)], Args); + tuple(0)], Args); builtin_to_scode(_Env, event, [_] = _Args) -> ?TODO(fate_event_instruction); builtin_to_scode(_Env, map_empty, []) -> @@ -409,7 +409,7 @@ builtin_to_scode(Env, abort, [_] = Args) -> call_to_scode(Env, aeb_fate_ops:abort(?a), Args); builtin_to_scode(Env, chain_spend, [_, _] = Args) -> call_to_scode(Env, [aeb_fate_ops:spend(?a, ?a), - aeb_fate_ops:tuple(0)], Args); + tuple(0)], Args); builtin_to_scode(Env, chain_balance, [_] = Args) -> call_to_scode(Env, aeb_fate_ops:balance_other(?a, ?a), Args); builtin_to_scode(Env, chain_block_hash, [_] = Args) -> @@ -516,6 +516,9 @@ op_to_scode(int_to_str) -> aeb_fate_ops:int_to_str(?a, ?a). %% easier, and specialize to PUSH (which is cheaper) at the end. push(A) -> aeb_fate_ops:store(?a, A). +tuple(0) -> push(?i({tuple, {}})); +tuple(N) -> aeb_fate_ops:tuple(?a, N). + %% -- Phase II --------------------------------------------------------------- %% Optimize @@ -605,7 +608,7 @@ ann_writes([{switch, Arg, Type, Alts, Def} | Code], Writes, Acc) -> Writes1 = ordsets:union(Writes, ordsets:intersection([WritesDef | WritesAlts])), ann_writes(Code, Writes1, [{switch, Arg, Type, Alts1, Def1} | Acc]); ann_writes([I | Code], Writes, Acc) -> - Ws = var_writes(I), + Ws = [ W || W <- var_writes(I), not ?IsState(W) ], Writes1 = ordsets:union(Writes, Ws), Ann = #{ writes_in => Writes, writes_out => Writes1 }, ann_writes(Code, Writes1, [{i, Ann, I} | Acc]); @@ -662,13 +665,13 @@ attributes(I) -> {'SWITCH_V3', A, _, _, _} -> Impure(pc, A); {'SWITCH_VN', A, _} -> Impure(pc, A); {'PUSH', A} -> Pure(?a, A); - 'DUPA' -> Pure(?a, []); + 'DUPA' -> Pure(?a, ?a); {'DUP', A} -> Pure(?a, A); {'POP', A} -> Pure(A, ?a); {'STORE', A, B} -> Pure(A, B); 'INCA' -> Pure(?a, ?a); {'INC', A} -> Pure(A, A); - 'DECA' -> Pure(?a, []); + 'DECA' -> Pure(?a, ?a); {'DEC', A} -> Pure(A, A); {'ADD', A, B, C} -> Pure(A, [B, C]); {'SUB', A, B, C} -> Pure(A, [B, C]); @@ -685,7 +688,7 @@ attributes(I) -> {'AND', A, B, C} -> Pure(A, [B, C]); {'OR', A, B, C} -> Pure(A, [B, C]); {'NOT', A, B} -> Pure(A, B); - {'TUPLE', _} -> Pure(?a, []); + {'TUPLE', A, N} -> Pure(A, [?a || N > 0]); {'ELEMENT', A, B, C} -> Pure(A, [B, C]); {'SETELEMENT', A, B, C, D} -> Pure(A, [B, C, D]); {'MAP_EMPTY', A} -> Pure(A, []); @@ -870,8 +873,7 @@ merge_rules() -> rules() -> merge_rules() ++ - [?RULE(r_dup_to_push), - ?RULE(r_swap_push), + [?RULE(r_swap_push), ?RULE(r_swap_write), ?RULE(r_constant_propagation), ?RULE(r_prune_impossible_branches), @@ -880,11 +882,6 @@ rules() -> ]. %% Removing pushes that are immediately consumed. -r_push_consume({i, Ann1, {'STORE', ?a, A}}, [{i, Ann2, {'POP', B}} | Code]) -> - case live_out(B, Ann2) of - true -> {[{i, merge_ann(Ann1, Ann2), {'STORE', B, A}}], Code}; - false -> {[], Code} - end; r_push_consume({i, Ann1, {'STORE', ?a, A}}, Code) -> inline_push(Ann1, A, 0, Code, []); %% Writing directly to memory instead of going through the accumulator. @@ -930,14 +927,6 @@ split_stack_arg(N, [A | As], Acc) -> true -> N end, split_stack_arg(N1, As, [A | Acc]). -%% Changing PUSH A, DUPA to PUSH A, PUSH A enables further optimisations -r_dup_to_push({i, Ann1, Push={'STORE', ?a, _}}, [{i, Ann2, 'DUPA'} | Code]) -> - #{ live_in := LiveIn } = Ann1, - Ann1_ = Ann1#{ live_out => LiveIn }, - Ann2_ = Ann2#{ live_in => LiveIn }, - {[{i, Ann1_, Push}, {i, Ann2_, Push}], Code}; -r_dup_to_push(_, _) -> false. - %% Move PUSH A past non-stack instructions. r_swap_push(Push = {i, _, {'STORE', ?a, _}}, [I | Code]) -> case independent(Push, I) of