aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/beam_peep.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2018-08-24 10:10:15 +0200
committerBjörn Gustavsson <[email protected]>2018-08-24 10:10:15 +0200
commit9facb02b91979ef90b47ac0a54d1eb71fdaa1ee1 (patch)
tree157b93e73c57080c88a8be1be821783403d0be3e /lib/compiler/src/beam_peep.erl
parent35979da59dd3c88601ed73a5eeb9054bbd28b5a1 (diff)
parentb3af7a279312a6203865d13b5885960cd187bda2 (diff)
downloadotp-9facb02b91979ef90b47ac0a54d1eb71fdaa1ee1.tar.gz
otp-9facb02b91979ef90b47ac0a54d1eb71fdaa1ee1.tar.bz2
otp-9facb02b91979ef90b47ac0a54d1eb71fdaa1ee1.zip
Merge branch 'bjorn/compiler/ssa'
* bjorn/compiler/ssa: Travis CI: Run the SSA linter in the Linux64SmokeTest build Remove retired compiler passes Introduce a new SSA-based intermediate format hipe_beam_to_icode: Correct translation of get_map_elements beam_dead: Remove shortcut of binary matching instruction beam_bs: Remove optimizations that are easier done on SSA format Don't run unsafe compiler passes Simplify optimizations by introducing is_nil late beam_utils: Make is_tagged_tuple a pure test beam_except: Enhance recognition of function_clause exceptions beam_validator: Infer the types of copies in a smarter way beam_validator: Improve merge of cons and literal list beam_validator: Strengthen validation of func_info beam_validator: Allow get_tuple_element before dsetelement beam_validator: Don't transfer state to labels that can't be reached beam_validator: Improve type analysis for tuples beam_validator: Be more careful when updating try/catch state beam_trim: Handle an empty list of instructions v3_core: Number argument variables in ascending order Teach binary instructions to use Y registers as destination OTP-14894
Diffstat (limited to 'lib/compiler/src/beam_peep.erl')
-rw-r--r--lib/compiler/src/beam_peep.erl69
1 files changed, 55 insertions, 14 deletions
diff --git a/lib/compiler/src/beam_peep.erl b/lib/compiler/src/beam_peep.erl
index 2b8dd40e29..74da6aa704 100644
--- a/lib/compiler/src/beam_peep.erl
+++ b/lib/compiler/src/beam_peep.erl
@@ -101,23 +101,13 @@ peep([{select,Op,R,F,Vls0}|Is], SeenTests0, Acc0) ->
I = {jump,F},
peep([I|Is], gb_sets:empty(), Acc0);
[{atom,_}=Value,Lbl] when Op =:= select_val ->
- %% Single value left. Convert to regular test and pop redundant tests.
+ %% Single value left. Convert to regular test.
Is1 = [{test,is_eq_exact,F,[R,Value]},{jump,Lbl}|Is],
- case Acc0 of
- [{test,is_atom,F,[R]}|Acc] ->
- peep(Is1, SeenTests0, Acc);
- _ ->
- peep(Is1, SeenTests0, Acc0)
- end;
+ peep(Is1, SeenTests0, Acc0);
[{integer,_}=Value,Lbl] when Op =:= select_val ->
- %% Single value left. Convert to regular test and pop redundant tests.
+ %% Single value left. Convert to regular test.
Is1 = [{test,is_eq_exact,F,[R,Value]},{jump,Lbl}|Is],
- case Acc0 of
- [{test,is_integer,F,[R]}|Acc] ->
- peep(Is1, SeenTests0, Acc);
- _ ->
- peep(Is1, SeenTests0, Acc0)
- end;
+ peep(Is1, SeenTests0, Acc0);
[Arity,Lbl] when Op =:= select_tuple_arity ->
%% Single value left. Convert to regular test
Is1 = [{test,test_arity,F,[R,Arity]},{jump,Lbl}|Is],
@@ -126,6 +116,21 @@ peep([{select,Op,R,F,Vls0}|Is], SeenTests0, Acc0) ->
I = {select,Op,R,F,Vls},
peep(Is, gb_sets:empty(), [I|Acc0])
end;
+peep([{get_map_elements,Fail,Src,List}=I|Is], _SeenTests, Acc0) ->
+ SeenTests = gb_sets:empty(),
+ case simplify_get_map_elements(Fail, Src, List, Acc0) of
+ {ok,Acc} ->
+ peep(Is, SeenTests, Acc);
+ error ->
+ peep(Is, SeenTests, [I|Acc0])
+ end;
+peep([{test,has_map_fields,Fail,Ops}=I|Is], SeenTests, Acc0) ->
+ case simplify_has_map_fields(Fail, Ops, Acc0) of
+ {ok,Acc} ->
+ peep(Is, SeenTests, Acc);
+ error ->
+ peep(Is, SeenTests, [I|Acc0])
+ end;
peep([{test,Op,_,Ops}=I|Is], SeenTests0, Acc) ->
case beam_utils:is_pure_test(I) of
false ->
@@ -176,3 +181,39 @@ prune_redundant_values([_Val,F|Vls], F) ->
prune_redundant_values([Val,Lbl|Vls], F) ->
[Val,Lbl|prune_redundant_values(Vls, F)];
prune_redundant_values([], _) -> [].
+
+simplify_get_map_elements(Fail, Src, {list,[Key,Dst]},
+ [{get_map_elements,Fail,Src,{list,List1}}|Acc]) ->
+ case are_keys_literals([Key]) andalso are_keys_literals(List1) of
+ true ->
+ case member(Key, List1) of
+ true ->
+ %% The key is already in the other list. That is
+ %% very unusual, because there are optimizations to get
+ %% rid of duplicate keys. Therefore, don't try to
+ %% do anything smart here; just keep the
+ %% get_map_elements instructions separate.
+ error;
+ false ->
+ List = [Key,Dst|List1],
+ {ok,[{get_map_elements,Fail,Src,{list,List}}|Acc]}
+ end;
+ false ->
+ error
+ end;
+simplify_get_map_elements(_, _, _, _) -> error.
+
+simplify_has_map_fields(Fail, [Src|Keys0],
+ [{test,has_map_fields,Fail,[Src|Keys1]}|Acc]) ->
+ case are_keys_literals(Keys0) andalso are_keys_literals(Keys1) of
+ true ->
+ Keys = Keys0 ++ Keys1,
+ {ok,[{test,has_map_fields,Fail,[Src|Keys]}|Acc]};
+ false ->
+ error
+ end;
+simplify_has_map_fields(_, _, _) -> error.
+
+are_keys_literals([{x,_}|_]) -> false;
+are_keys_literals([{y,_}|_]) -> false;
+are_keys_literals([_|_]) -> true.