aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/test/bs_match_SUITE.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2018-01-15 11:25:53 +0100
committerBjörn Gustavsson <[email protected]>2018-01-16 15:01:34 +0100
commitee072786553683dcd2947a3a432da68a79c05b63 (patch)
treedcf0aac6db976da0499554983aff58a784a04b21 /lib/compiler/test/bs_match_SUITE.erl
parentfd30cdac0f62c70336330d94ac944bb110932cc2 (diff)
downloadotp-ee072786553683dcd2947a3a432da68a79c05b63.tar.gz
otp-ee072786553683dcd2947a3a432da68a79c05b63.tar.bz2
otp-ee072786553683dcd2947a3a432da68a79c05b63.zip
sys_core_bsm: Rearrange arguments to enable delayed sub binary creation
Argument order can prevent the delayed sub binary creation. Here is an example directly from the Efficiency Guide: non_opt_eq([H|T1], <<H,T2/binary>>) -> non_opt_eq(T1, T2); non_opt_eq([_|_], <<_,_/binary>>) -> false; non_opt_eq([], <<>>) -> true. When compiling with the bin_opt_info option, there will be a suggestion to change the argument order. It turns out sys_core_bsm can itself change the order, not the order of the arguments of themselves, but the order in which the arguments are matched. Here is how it can be rewritten in pseudo Core Erlang code: non_opt_eq(Arg1, Arg2) -> case < Arg2,Arg1 > of < <<H1,T2/binary>>, [H2|T1] > when H1 =:= H2 -> non_opt_eq(T1, T2); < <<_,T2/binary>ffff>, [_|T1] > -> false; < <<>>, [] >> -> true end. When rewritten like this, the bs_start_match2 instruction will be the first instruction in the function and it will be possible to store the match context in the same register as the binary ({x,1} in this case) and to delay the creation of sub binaries. The switching of matching order also enables many other simplifications in sys_core_bsm, since there is no longer any need to pass the position of the pattern as an argument. We will update the Efficiency Guide in a separate branch before the release of OTP 21.
Diffstat (limited to 'lib/compiler/test/bs_match_SUITE.erl')
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl19
1 files changed, 17 insertions, 2 deletions
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 7557d6d57b..4bd5e8e2e1 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -40,7 +40,7 @@
map_and_binary/1,unsafe_branch_caching/1,
bad_literals/1,good_literals/1,constant_propagation/1,
parse_xml/1,get_payload/1,escape/1,num_slots_different/1,
- beam_bsm/1,guard/1,is_ascii/1]).
+ beam_bsm/1,guard/1,is_ascii/1,non_opt_eq/1]).
-export([coverage_id/1,coverage_external_ignore/2]).
@@ -73,7 +73,7 @@ groups() ->
map_and_binary,unsafe_branch_caching,
bad_literals,good_literals,constant_propagation,parse_xml,
get_payload,escape,num_slots_different,
- beam_bsm,guard,is_ascii]}].
+ beam_bsm,guard,is_ascii,non_opt_eq]}].
init_per_suite(Config) ->
@@ -1654,6 +1654,21 @@ do_is_ascii(<<C,_/binary>>) when C >= 16#80 ->
do_is_ascii(<<_, T/binary>>) ->
do_is_ascii(T).
+non_opt_eq(_Config) ->
+ true = non_opt_eq([], <<>>),
+ true = non_opt_eq([$a], <<$a>>),
+ false = non_opt_eq([$a], <<$b>>),
+ ok.
+
+%% An example from the Efficiency Guide. It used to be not optimized,
+%% but now it can be optimized.
+
+non_opt_eq([H|T1], <<H,T2/binary>>) ->
+ non_opt_eq(T1, T2);
+non_opt_eq([_|_], <<_,_/binary>>) ->
+ false;
+non_opt_eq([], <<>>) ->
+ true.
check(F, R) ->
R = F().