diff options
author | Björn Gustavsson <[email protected]> | 2019-05-22 11:28:19 +0200 |
---|---|---|
committer | GitHub <[email protected]> | 2019-05-22 11:28:19 +0200 |
commit | 48e1cc6a6f7bebacd5fb060bfd65ececbabfa6a1 (patch) | |
tree | 833fa41fe780cf9a5b9f03f5d64143e115d46b36 /lib/compiler/src/beam_block.erl | |
parent | 13833d876d103c03df4967e1fb249cdb8d30bc0b (diff) | |
parent | 18dc9a8099d1ad8f52b9db7bd251bcbfd632ce5e (diff) | |
download | otp-48e1cc6a6f7bebacd5fb060bfd65ececbabfa6a1.tar.gz otp-48e1cc6a6f7bebacd5fb060bfd65ececbabfa6a1.tar.bz2 otp-48e1cc6a6f7bebacd5fb060bfd65ececbabfa6a1.zip |
Merge pull request #2242 from bjorng/bjorn/add-swap-instruction
Make the swap instruction known to the compiler
Diffstat (limited to 'lib/compiler/src/beam_block.erl')
-rw-r--r-- | lib/compiler/src/beam_block.erl | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index 707974b2c1..a734ca3a10 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -33,8 +33,9 @@ module({Mod,Exp,Attr,Fs0,Lc}, _Opts) -> function({function,Name,Arity,CLabel,Is0}) -> try - Is1 = blockify(Is0), - Is = embed_lines(Is1), + Is1 = swap_opt(Is0), + Is2 = blockify(Is1), + Is = embed_lines(Is2), {function,Name,Arity,CLabel,Is} catch Class:Error:Stack -> @@ -42,6 +43,40 @@ function({function,Name,Arity,CLabel,Is0}) -> erlang:raise(Class, Error, Stack) end. +%%% +%%% Try to use a `swap` instruction instead of a sequence of moves. +%%% +%%% Note that beam_ssa_codegen generates `swap` instructions only for +%%% the moves within a single SSA instruction (such as `call`), not +%%% for the moves generated by a sequence of SSA instructions. +%%% Therefore, this optimization is needed. +%%% + +swap_opt([{move,Reg1,{x,X}=Temp}=Move1, + {move,Reg2,Reg1}=Move2, + {move,Temp,Reg2}=Move3|Is]) when Reg1 =/= Temp -> + case is_unused(X, Is) of + true -> + [{swap,Reg1,Reg2}|swap_opt(Is)]; + false -> + [Move1|swap_opt([Move2,Move3|Is])] + end; +swap_opt([I|Is]) -> + [I|swap_opt(Is)]; +swap_opt([]) -> []. + +is_unused(X, [{call,A,_}|_]) when A =< X -> true; +is_unused(X, [{call_ext,A,_}|_]) when A =< X -> true; +is_unused(X, [{make_fun2,_,_,_,A}|_]) when A =< X -> true; +is_unused(X, [{move,Src,Dst}|Is]) -> + case {Src,Dst} of + {{x,X},_} -> false; + {_,{x,X}} -> true; + {_,_} -> is_unused(X, Is) + end; +is_unused(X, [{line,_}|Is]) -> is_unused(X, Is); +is_unused(_, _) -> false. + %% blockify(Instructions0) -> Instructions %% Collect sequences of instructions to basic blocks. %% Also do some simple optimations on instructions outside the blocks. |