aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/beam_a.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2012-10-10 16:00:04 +0200
committerBjörn Gustavsson <[email protected]>2012-10-10 16:00:04 +0200
commitb16c127d4dc2bb070d6e98e5c4cdc38220708a13 (patch)
tree60e0fe128f9fe6d36354952d70f06463683a112d /lib/compiler/src/beam_a.erl
parent55358002ddfa9f19e4142677d1ad4bd0a1760c0a (diff)
parente1aa422290b09a68bd761cbd0e70bd48442009b3 (diff)
downloadotp-b16c127d4dc2bb070d6e98e5c4cdc38220708a13.tar.gz
otp-b16c127d4dc2bb070d6e98e5c4cdc38220708a13.tar.bz2
otp-b16c127d4dc2bb070d6e98e5c4cdc38220708a13.zip
Merge branch 'bjorn/compiler/minor-optimization-polishing/OTP-10193'
* bjorn/compiler/minor-optimization-polishing/OTP-10193: (25 commits) beam_bsm: Handle calls slightly better Break apart tail-recursive call instructions Represent the 'send' instruction as a call_ext/2 instruction Rewrite select_val and select_tuple_arity to a select instruction Rewrite binary creation instructions to bs_init instructions Rewrite bs_add, bs_utf*_size to BIF instructions in optimizations Rewrite bs_put* instructions to a generic bs_put instruction Refactor removal of unused labels Introduce the mandatory beam_a and beam_z passes compile: Fix bug in selection of passes beam_receive: Optimize receives using refs created by spawn_monitor/{1,3} compile: Give a friendler error message if a parse transform cannot be found beam_jump: Don't move a block which can be entered via a fallthrough beam_jump: Fix broken optimization v3_kernel: Fix match code for matched out segment size in multiple clauses Improve binary matching of literals v3_codegen: Combine adjacent bs_match_string instructions beam_bool: Recognize more safe optimizations beam_utils: Correct usage calculations for GC BIFs in blocks beam_utils:live_opt/1: Correct liveness calculation for 'try' ...
Diffstat (limited to 'lib/compiler/src/beam_a.erl')
-rw-r--r--lib/compiler/src/beam_a.erl97
1 files changed, 97 insertions, 0 deletions
diff --git a/lib/compiler/src/beam_a.erl b/lib/compiler/src/beam_a.erl
new file mode 100644
index 0000000000..1c51226314
--- /dev/null
+++ b/lib/compiler/src/beam_a.erl
@@ -0,0 +1,97 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Purpose: Run directly after code generation to do any normalization
+%% or preparation to simplify the optimization passes.
+%% (Mandatory.)
+
+-module(beam_a).
+
+-export([module/2]).
+
+module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
+ Fs = [function(F) || F <- Fs0],
+ {ok,{Mod,Exp,Attr,Fs,Lc}}.
+
+function({function,Name,Arity,CLabel,Is0}) ->
+ try
+ %% Rename certain operations to simplify the optimization passes.
+ Is1 = rename_instrs(Is0),
+
+ %% Remove unusued labels for cleanliness and to help
+ %% optimization passes and HiPE.
+ Is = beam_jump:remove_unused_labels(Is1),
+ {function,Name,Arity,CLabel,Is}
+ catch
+ Class:Error ->
+ Stack = erlang:get_stacktrace(),
+ io:fwrite("Function: ~w/~w\n", [Name,Arity]),
+ erlang:raise(Class, Error, Stack)
+ end.
+
+rename_instrs([{apply_last,A,N}|Is]) ->
+ [{apply,A},{deallocate,N},return|rename_instrs(Is)];
+rename_instrs([{call_last,A,F,N}|Is]) ->
+ [{call,A,F},{deallocate,N},return|rename_instrs(Is)];
+rename_instrs([{call_ext_last,A,F,N}|Is]) ->
+ [{call_ext,A,F},{deallocate,N},return|rename_instrs(Is)];
+rename_instrs([{call_only,A,F}|Is]) ->
+ [{call,A,F},return|rename_instrs(Is)];
+rename_instrs([{call_ext_only,A,F}|Is]) ->
+ [{call_ext,A,F},return|rename_instrs(Is)];
+rename_instrs([I|Is]) ->
+ [rename_instr(I)|rename_instrs(Is)];
+rename_instrs([]) -> [].
+
+rename_instr({bs_put_binary=I,F,Sz,U,Fl,Src}) ->
+ {bs_put,F,{I,U,Fl},[Sz,Src]};
+rename_instr({bs_put_float=I,F,Sz,U,Fl,Src}) ->
+ {bs_put,F,{I,U,Fl},[Sz,Src]};
+rename_instr({bs_put_integer=I,F,Sz,U,Fl,Src}) ->
+ {bs_put,F,{I,U,Fl},[Sz,Src]};
+rename_instr({bs_put_utf8=I,F,Fl,Src}) ->
+ {bs_put,F,{I,Fl},[Src]};
+rename_instr({bs_put_utf16=I,F,Fl,Src}) ->
+ {bs_put,F,{I,Fl},[Src]};
+rename_instr({bs_put_utf32=I,F,Fl,Src}) ->
+ {bs_put,F,{I,Fl},[Src]};
+%% rename_instr({bs_put_string,_,_}=I) ->
+%% {bs_put,{f,0},I,[]};
+rename_instr({bs_add=I,F,[Src1,Src2,U],Dst}) when is_integer(U) ->
+ {bif,I,F,[Src1,Src2,{integer,U}],Dst};
+rename_instr({bs_utf8_size=I,F,Src,Dst}) ->
+ {bif,I,F,[Src],Dst};
+rename_instr({bs_utf16_size=I,F,Src,Dst}) ->
+ {bif,I,F,[Src],Dst};
+rename_instr({bs_init2=I,F,Sz,Extra,Live,Flags,Dst}) ->
+ {bs_init,F,{I,Extra,Flags},Live,[Sz],Dst};
+rename_instr({bs_init_bits=I,F,Sz,Extra,Live,Flags,Dst}) ->
+ {bs_init,F,{I,Extra,Flags},Live,[Sz],Dst};
+rename_instr({bs_append=I,F,Sz,Extra,Live,U,Src,Flags,Dst}) ->
+ {bs_init,F,{I,Extra,U,Flags},Live,[Sz,Src],Dst};
+rename_instr({bs_private_append=I,F,Sz,U,Src,Flags,Dst}) ->
+ {bs_init,F,{I,U,Flags},none,[Sz,Src],Dst};
+rename_instr(bs_init_writable=I) ->
+ {bs_init,{f,0},I,1,[{x,0}],{x,0}};
+rename_instr({select_val=I,Reg,Fail,{list,List}}) ->
+ {select,I,Reg,Fail,List};
+rename_instr({select_tuple_arity=I,Reg,Fail,{list,List}}) ->
+ {select,I,Reg,Fail,List};
+rename_instr(send) ->
+ {call_ext,2,send};
+rename_instr(I) -> I.