aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-09-22 06:14:36 +0200
committerBjörn Gustavsson <[email protected]>2015-09-28 10:26:39 +0200
commit58a0c1c6c7efdb1f1250edec1b5fcd5eb72e99b9 (patch)
treea7f327cfe47316dfef8bbf52d93f76453b6f8bfc
parent8372f56a06ef24cf4455a54e15d876ab6ca8c570 (diff)
downloadotp-58a0c1c6c7efdb1f1250edec1b5fcd5eb72e99b9.tar.gz
otp-58a0c1c6c7efdb1f1250edec1b5fcd5eb72e99b9.tar.bz2
otp-58a0c1c6c7efdb1f1250edec1b5fcd5eb72e99b9.zip
beam_dead: Optimize select_val instructions
In a select_val instruction, values associated with a label which is the same as the failure label can be removed. We already do this optimization in beam_clean, but it is better do this sort of optimization before the beam_jump pass. Also rewrite a select_val instruction with a single value to is_eq_exact instruction followed by a jump instruction.
-rw-r--r--lib/compiler/src/beam_dead.erl26
1 files changed, 25 insertions, 1 deletions
diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl
index 0cb5040177..fcd108bd89 100644
--- a/lib/compiler/src/beam_dead.erl
+++ b/lib/compiler/src/beam_dead.erl
@@ -239,10 +239,18 @@ backward([{test,is_eq_exact,Fail,[Dst,{integer,Arity}]}=I|
backward([{label,Lbl}=L|Is], D, Acc) ->
backward(Is, beam_utils:index_label(Lbl, Acc, D), [L|Acc]);
backward([{select,select_val,Reg,{f,Fail0},List0}|Is], D, Acc) ->
- List = shortcut_select_list(List0, Reg, D, []),
+ List1 = shortcut_select_list(List0, Reg, D, []),
Fail1 = shortcut_label(Fail0, D),
Fail = shortcut_bs_test(Fail1, Is, D),
+ List = prune_redundant(List1, Fail),
case List of
+ [] ->
+ Jump = {jump,{f,Fail}},
+ backward([Jump|Is], D, Acc);
+ [V,F] ->
+ Test = {test,is_eq_exact,{f,Fail},[Reg,V]},
+ Jump = {jump,F},
+ backward([Jump,Test|Is], D, Acc);
[{atom,B1},F,{atom,B2},F] when B1 =:= not B2 ->
Test = {test,is_boolean,{f,Fail},[Reg]},
Jump = {jump,F},
@@ -307,6 +315,16 @@ backward([{test,Op,{f,To0},Ops0}|Is], D, Acc) ->
%% An is_atom test before an is_boolean test (with the
%% same failure label) is redundant.
backward(Is, D, Acc);
+ {{test,is_atom,Fail,[R]},
+ [{test,is_eq_exact,Fail,[R,{atom,_}]}|_]} ->
+ %% An is_atom test before a comparison with an atom (with
+ %% the same failure label) is redundant.
+ backward(Is, D, Acc);
+ {{test,is_integer,Fail,[R]},
+ [{test,is_eq_exact,Fail,[R,{integer,_}]}|_]} ->
+ %% An is_integer test before a comparison with an integer
+ %% (with the same failure label) is redundant.
+ backward(Is, D, Acc);
{{test,_,_,_},_} ->
%% Still a test instruction. Done.
backward(Is, D, [I|Acc]);
@@ -366,6 +384,12 @@ shortcut_label(To0, D) ->
shortcut_select_label(To, Reg, Lit, D) ->
shortcut_rel_op(To, is_ne_exact, [Reg,Lit], D).
+prune_redundant([_,{f,Fail}|T], Fail) ->
+ prune_redundant(T, Fail);
+prune_redundant([V,F|T], Fail) ->
+ [V,F|prune_redundant(T, Fail)];
+prune_redundant([], _) -> [].
+
%% Replace a comparison operator with a test instruction and a jump.
%% For example, if we have this code:
%%