diff options
Diffstat (limited to 'lib/compiler')
-rw-r--r-- | lib/compiler/src/beam_jump.erl | 14 | ||||
-rw-r--r-- | lib/compiler/test/receive_SUITE_data/ref_opt/yes_10.erl | 13 | ||||
-rw-r--r-- | lib/compiler/test/receive_SUITE_data/ref_opt/yes_11.erl | 21 |
3 files changed, 44 insertions, 4 deletions
diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl index 79cdc8e179..e7025ea6e8 100644 --- a/lib/compiler/src/beam_jump.erl +++ b/lib/compiler/src/beam_jump.erl @@ -46,10 +46,13 @@ %%% such as a jump that never transfers control to the instruction %%% following it. %%% -%%% (2) case_end, if_end, and badmatch, and function calls that cause an -%%% exit (such as calls to exit/1) are moved to the end of the function. -%%% The purpose is to allow further optimizations at the place from -%%% which the code was moved. +%%% (2) Short sequences starting with a label and ending in case_end, if_end, +%%% and badmatch, and function calls that cause an exit (such as calls +%%% to exit/1) are moved to the end of the function, but only if the +%%% the block is not entered via a fallthrough. The purpose of this move +%%% is to allow further optimizations at the place from which the +%%% code was moved (a jump around the block could be replaced with a +%%% fallthrough). %%% %%% (3) Any unreachable code is removed. Unreachable code is code %%% after jump, call_last and other instructions which never @@ -232,6 +235,9 @@ extract_seq_1([{line,_}=Line|Is], Acc) -> extract_seq_1(Is, [Line|Acc]); extract_seq_1([{label,_},{func_info,_,_,_}|_], _) -> no; +extract_seq_1([{label,Lbl},{jump,{f,Lbl}}|_], _) -> + %% Don't move a sequence which have a fallthrough entering it. + no; extract_seq_1([{label,_}=Lbl|Is], Acc) -> {yes,[Lbl|Acc],Is}; extract_seq_1(_, _) -> no. diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_10.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_10.erl new file mode 100644 index 0000000000..7ce6e6103c --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_10.erl @@ -0,0 +1,13 @@ +-module(yes_10). +-compile(export_all). + +?MODULE() -> + ok. + +f() -> + Ref = make_ref(), + receive + %% Artifical example to cover more code in beam_receive. + {X,Y} when Ref =/= X, Ref =:= Y -> + ok + end. diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_11.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_11.erl new file mode 100644 index 0000000000..62f439fc42 --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_11.erl @@ -0,0 +1,21 @@ +-module(yes_11). +-compile(export_all). + +?MODULE() -> + ok. + +%% Artifical example to cover more code in beam_receive. +do_call(Process, Request) -> + Mref = erlang:monitor(process, Process), + Process ! Request, + receive + {X,Y,Z} when Mref =/= X, Z =:= 42, Mref =:= Y -> + error; + {X,Y,_} when Mref =/= X, Mref =:= Y -> + error; + {Mref, Reply} -> + erlang:demonitor(Mref, [flush]), + {ok, Reply}; + {'DOWN', Mref, _, _, _} -> + error + end. |