aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/beam_ssa_opt.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2018-08-21 08:17:24 +0200
committerBjörn Gustavsson <[email protected]>2018-09-12 14:19:04 +0200
commitbe092fb5fecfc382a45681d8de07fda27d77bf26 (patch)
treee25b4b4bec4ec57299b0a0684905ccf79e5289ab /lib/compiler/src/beam_ssa_opt.erl
parentd3551827cc0221437098c5afa492637072f8a771 (diff)
downloadotp-be092fb5fecfc382a45681d8de07fda27d77bf26.tar.gz
otp-be092fb5fecfc382a45681d8de07fda27d77bf26.tar.bz2
otp-be092fb5fecfc382a45681d8de07fda27d77bf26.zip
Optimize 'and' and 'or' instructions
Diffstat (limited to 'lib/compiler/src/beam_ssa_opt.erl')
-rw-r--r--lib/compiler/src/beam_ssa_opt.erl45
1 files changed, 39 insertions, 6 deletions
diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl
index da466a3316..257e036719 100644
--- a/lib/compiler/src/beam_ssa_opt.erl
+++ b/lib/compiler/src/beam_ssa_opt.erl
@@ -941,6 +941,22 @@ misc_opt_is([#b_set{op=phi}=I0|Is], Sub0, Acc) ->
false ->
misc_opt_is(Is, Sub0, [I|Acc])
end;
+misc_opt_is([#b_set{op={bif,'and'}}=I0], Sub, Acc) ->
+ #b_set{dst=Dst,args=Args} = I = sub(I0, Sub),
+ case eval_and(Args) of
+ error ->
+ misc_opt_is([], Sub, [I|Acc]);
+ Val ->
+ misc_opt_is([], Sub#{Dst=>Val}, Acc)
+ end;
+misc_opt_is([#b_set{op={bif,'or'}}=I0], Sub, Acc) ->
+ #b_set{dst=Dst,args=Args} = I = sub(I0, Sub),
+ case eval_or(Args) of
+ error ->
+ misc_opt_is([], Sub, [I|Acc]);
+ Val ->
+ misc_opt_is([], Sub#{Dst=>Val}, Acc)
+ end;
misc_opt_is([#b_set{}=I0|Is], Sub, Acc) ->
#b_set{op=Op,dst=Dst,args=Args} = I = sub(I0, Sub),
case make_literal(Op, Args) of
@@ -973,6 +989,20 @@ make_literal_list([_|_], _) ->
make_literal_list([], Acc) ->
reverse(Acc).
+eval_and(Args) ->
+ case Args of
+ [_,#b_literal{val=false}=Res] -> Res;
+ [Res,#b_literal{val=true}] -> Res;
+ [_,_] -> error
+ end.
+
+eval_or(Args) ->
+ case Args of
+ [Res,#b_literal{val=false}] -> Res;
+ [_,#b_literal{val=true}=Res] -> Res;
+ [_,_] -> error
+ end.
+
%%%
%%% Merge blocks.
%%%
@@ -1283,20 +1313,23 @@ rel2fam(S0) ->
S = sofs:rel2fam(S1),
sofs:to_external(S).
-sub(#b_set{op=phi,args=Args}=I, Sub) ->
+sub(I, Sub) ->
+ beam_ssa:normalize(sub_1(I, Sub)).
+
+sub_1(#b_set{op=phi,args=Args}=I, Sub) ->
I#b_set{args=[{sub_arg(A, Sub),P} || {A,P} <- Args]};
-sub(#b_set{args=Args}=I, Sub) ->
+sub_1(#b_set{args=Args}=I, Sub) ->
I#b_set{args=[sub_arg(A, Sub) || A <- Args]};
-sub(#b_br{bool=#b_var{}=Old}=Br, Sub) ->
+sub_1(#b_br{bool=#b_var{}=Old}=Br, Sub) ->
New = sub_arg(Old, Sub),
Br#b_br{bool=New};
-sub(#b_switch{arg=#b_var{}=Old}=Sw, Sub) ->
+sub_1(#b_switch{arg=#b_var{}=Old}=Sw, Sub) ->
New = sub_arg(Old, Sub),
Sw#b_switch{arg=New};
-sub(#b_ret{arg=#b_var{}=Old}=Ret, Sub) ->
+sub_1(#b_ret{arg=#b_var{}=Old}=Ret, Sub) ->
New = sub_arg(Old, Sub),
Ret#b_ret{arg=New};
-sub(Last, _) -> Last.
+sub_1(Last, _) -> Last.
sub_arg(#b_remote{mod=Mod,name=Name}=Rem, Sub) ->
Rem#b_remote{mod=sub_arg(Mod, Sub),name=sub_arg(Name, Sub)};