diff options
author | Björn Gustavsson <[email protected]> | 2016-11-18 12:06:42 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2016-11-18 12:06:42 +0100 |
commit | 79653c709f854e6fadd719ef5f079f66219c6bdf (patch) | |
tree | 2f2a3a1a3b1a06a5e458424da5cb88f9733ec56f /lib/compiler/src/beam_dead.erl | |
parent | f578f6c57438ac7dd11a3d113406a104f4064b26 (diff) | |
parent | 09f170e35cf9df8438ae42d48b51becff167b5b4 (diff) | |
download | otp-79653c709f854e6fadd719ef5f079f66219c6bdf.tar.gz otp-79653c709f854e6fadd719ef5f079f66219c6bdf.tar.bz2 otp-79653c709f854e6fadd719ef5f079f66219c6bdf.zip |
Merge branch 'bjorn/compiler/guards/PR-1232/OTP-14042'
* bjorn/compiler/guards/PR-1232/OTP-14042:
compile_SUITE: Make sure that guards are optimized
beam_dead: Remove redundant 'or' instruction
beam_dead: Remove redundant 'bif' instructions
Add test using LFE-generated Core Erlang modules
Remove beam_bool
v3_kernel: Generate optimized code for guards
sys_core_fold: Remove unnecessary calls to opt_bool_case/1
record_SUITE: Strengthen test of record access in guards
Diffstat (limited to 'lib/compiler/src/beam_dead.erl')
-rw-r--r-- | lib/compiler/src/beam_dead.erl | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl index 3606af9d75..9087586b58 100644 --- a/lib/compiler/src/beam_dead.erl +++ b/lib/compiler/src/beam_dead.erl @@ -266,12 +266,30 @@ backward([{jump,{f,To0}},{move,Src,Reg}=Move|Is], D, Acc) -> false -> backward([Move|Is], D, [Jump|Acc]); true -> backward([Jump|Is], D, Acc) end; -backward([{jump,{f,To}}=J|[{bif,Op,_,Ops,Reg}|Is]=Is0], D, Acc) -> +backward([{jump,{f,To}}=J|[{bif,Op,{f,BifFail},Ops,Reg}|Is]=Is0], D, Acc) -> try replace_comp_op(To, Reg, Op, Ops, D) of I -> backward(Is, D, I++Acc) catch - throw:not_possible -> backward(Is0, D, [J|Acc]) + throw:not_possible -> + case To =:= BifFail of + true -> + %% The bif instruction is redundant. See the comment + %% in the next clause for why there is no need to + %% test for liveness of Reg at label To. + backward([J|Is], D, Acc); + false -> + backward(Is0, D, [J|Acc]) + end end; +backward([{jump,{f,To}}=J|[{gc_bif,_,{f,To},_,_,_Dst}|Is]], D, Acc) -> + %% The gc_bif instruction is redundant, since either the gc_bif + %% instruction itself or the jump instruction will transfer control + %% to label To. Note that a gc_bif instruction does not assign its + %% destination register if the failure branch is taken; therefore, + %% the code at label To is not allowed to assume that the destination + %% register is initialized, and it is therefore no need to test + %% for liveness of the destination register at label To. + backward([J|Is], D, Acc); backward([{test,bs_start_match2,F,Live,[R,_]=Args,Ctxt}|Is], D, [{test,bs_match_string,F,[Ctxt,Bs]}, {test,bs_test_tail2,F,[Ctxt,0]}|Acc0]=Acc) -> @@ -361,6 +379,14 @@ backward([{kill,_}=I|Is], D, [{line,_},Exit|_]=Acc) -> false -> backward(Is, D, [I|Acc]); true -> backward(Is, D, Acc) end; +backward([{bif,'or',{f,To0},[Dst,{atom,false}],Dst}=I|Is], D, + [{test,is_eq_exact,{f,To},[Dst,{atom,true}]}|_]=Acc) -> + case shortcut_label(To0, D) of + To -> + backward(Is, D, Acc); + _ -> + backward(Is, D, [I|Acc]) + end; backward([I|Is], D, Acc) -> backward(Is, D, [I|Acc]); backward([], _D, Acc) -> Acc. @@ -379,6 +405,8 @@ shortcut_select_list([Lit,{f,To0}|T], Reg, D, Acc) -> shortcut_select_list(T, Reg, D, [{f,To},Lit|Acc]); shortcut_select_list([], _, _, Acc) -> reverse(Acc). +shortcut_label(0, _) -> + 0; shortcut_label(To0, D) -> case beam_utils:code_at(To0, D) of [{jump,{f,To}}|_] -> shortcut_label(To, D); |