LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File 1051-Optimize-matching-of-empty-binaries.patch of Package erlang (Project home:Ledest:erlang:20)

From 4ad250c85a1abb80b6e0a30855c8982d174b369c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Fri, 19 Jan 2018 12:37:49 +0100
Subject: [PATCH 1/3] Optimize matching of empty binaries

Extend an existing optimization in beam_dead to avoid
creating a match context when matching an empty binary.
---
 lib/compiler/src/beam_dead.erl       | 49 ++++++++++++++++++++++++------------
 lib/compiler/test/bs_match_SUITE.erl |  8 ++++++
 2 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl
index da944f3ce6..dbbaae05eb 100644
--- a/lib/compiler/src/beam_dead.erl
+++ b/lib/compiler/src/beam_dead.erl
@@ -294,24 +294,25 @@ backward([{jump,{f,To}}=J|[{gc_bif,_,{f,To},_,_,_Dst}|Is]], D, Acc) ->
     %% 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) ->
+backward([{test,bs_start_match2,F,Live,[Src,_]=Args,Ctxt}|Is], D, Acc0) ->
     {f,To0} = F,
-    case beam_utils:is_killed(Ctxt, Acc0, D) of
-	true ->
-	    To = shortcut_bs_context_to_binary(To0, R, D),
-	    Eq = {test,is_eq_exact,{f,To},[R,{literal,Bs}]},
-	    backward(Is, D, [Eq|Acc0]);
-	false ->
-	    To = shortcut_bs_start_match(To0, R, D),
-	    I = {test,bs_start_match2,{f,To},Live,Args,Ctxt},
-	    backward(Is, D, [I|Acc])
+    case test_bs_literal(F, Ctxt, D, Acc0) of
+        {none,Acc} ->
+            %% Ctxt killed immediately after bs_start_match2.
+            To = shortcut_bs_context_to_binary(To0, Src, D),
+            I = {test,is_bitstr,{f,To},[Src]},
+            backward(Is, D, [I|Acc]);
+        {Literal,Acc} ->
+            %% Ctxt killed after matching a literal.
+            To = shortcut_bs_context_to_binary(To0, Src, D),
+            Eq = {test,is_eq_exact,{f,To},[Src,{literal,Literal}]},
+            backward(Is, D, [Eq|Acc]);
+        not_killed ->
+            %% Ctxt not killed. Not much to do.
+            To = shortcut_bs_start_match(To0, Src, D),
+            I = {test,bs_start_match2,{f,To},Live,Args,Ctxt},
+            backward(Is, D, [I|Acc0])
     end;
-backward([{test,bs_start_match2,{f,To0},Live,[Src|_]=Info,Dst}|Is], D, Acc) ->
-    To = shortcut_bs_start_match(To0, Src, D),
-    I = {test,bs_start_match2,{f,To},Live,Info,Dst},
-    backward(Is, D, [I|Acc]);
 backward([{test,Op,{f,To0},Ops0}|Is], D, Acc) ->
     To1 = shortcut_bs_test(To0, Is, D),
     To2 = shortcut_label(To1, D),
@@ -511,6 +512,22 @@ remove_from_list(Lit, [Val,{f,_}=Fail|T]) ->
     [Val,Fail|remove_from_list(Lit, T)];
 remove_from_list(_, []) -> [].
 
+
+test_bs_literal(F, Ctxt, D,
+                [{test,bs_match_string,F,[Ctxt,Bs]},
+                 {test,bs_test_tail2,F,[Ctxt,0]}|Acc]) ->
+    test_bs_literal_1(Ctxt, Acc, D, Bs);
+test_bs_literal(F, Ctxt, D, [{test,bs_test_tail2,F,[Ctxt,0]}|Acc]) ->
+    test_bs_literal_1(Ctxt, Acc, D, <<>>);
+test_bs_literal(_, Ctxt, D, Acc) ->
+    test_bs_literal_1(Ctxt, Acc, D, none).
+
+test_bs_literal_1(Ctxt, Is, D, Literal) ->
+    case beam_utils:is_killed(Ctxt, Is, D) of
+        true -> {Literal,Is};
+        false -> not_killed
+    end.
+
 %% shortcut_bs_test(TargetLabel, ReversedInstructions, D) -> TargetLabel'
 %%  Try to shortcut the failure label for bit syntax matching.
 
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 4bd5e8e2e1..235956a714 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -678,6 +678,10 @@ coverage(Config) when is_list(Config) ->
     <<>> = coverage_per_key(<<4:32>>),
     <<$a,$b,$c>> = coverage_per_key(<<7:32,"abc">>),
 
+    binary = coverage_bitstring(<<>>),
+    binary = coverage_bitstring(<<7>>),
+    bitstring = coverage_bitstring(<<7:4>>),
+    other = coverage_bitstring([a]),
     ok.
 
 coverage_fold(Fun, Acc, <<H,T/binary>>) ->
@@ -768,6 +772,10 @@ coverage_per_key(<<BinSize:32,Bin/binary>> = B) ->
     true = (byte_size(B) =:= BinSize),
     Bin.
 
+coverage_bitstring(Bin) when is_binary(Bin) -> binary;
+coverage_bitstring(<<_/bitstring>>) -> bitstring;
+coverage_bitstring(_) -> other.
+
 multiple_uses(Config) when is_list(Config) ->
     {344,62879,345,<<245,159,1,89>>} = multiple_uses_1(<<1,88,245,159,1,89>>),
     true = multiple_uses_2(<<0,0,197,18>>),
-- 
2.16.0