LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File 1053-beam_type-Optimize-away-unnecessary-test_unit-instru.patch of Package erlang (Project home:Ledest:erlang:20)

From 1781ebe6cd61d0bbd1f8c4e55b42edebfdc45734 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Fri, 19 Jan 2018 14:38:54 +0100
Subject: [PATCH 3/3] beam_type: Optimize away unnecessary test_unit
 instructions

Optimize away unnecessary test_unit instructions that verify that
binaries are byte-aligned. In a tight loop, eliminating an
instruction can have a small but measurable improvement of the
execution time.
---
 lib/compiler/src/beam_type.erl        | 47 ++++++++++++++++++++++++++++++-----
 lib/compiler/test/beam_type_SUITE.erl | 42 +++++++++++++++++++++++++++++--
 2 files changed, 81 insertions(+), 8 deletions(-)

diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index 576557d35d..b2fabed2c5 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.erl
@@ -157,6 +157,21 @@ simplify_instr({select,select_val,Reg,_,_}=I, Ts) ->
          _ ->
              I
      end];
+simplify_instr({test,bs_test_unit,_,[Src,Unit]}=I, Ts) ->
+    case tdb_find(Src, Ts) of
+        {binary,U} when U rem Unit =:= 0 -> [];
+        _ -> [I]
+    end;
+simplify_instr({test,is_binary,_,[Src]}=I, Ts) ->
+    case tdb_find(Src, Ts) of
+        {binary,U} when U rem 8 =:= 0 -> [];
+        _ -> [I]
+    end;
+simplify_instr({test,is_bitstr,_,[Src]}=I, Ts) ->
+    case tdb_find(Src, Ts) of
+        {binary,_} -> [];
+        _ -> [I]
+    end;
 simplify_instr(I, _) -> [I].
 
 simplify_select_val_int({select,select_val,R,_,L0}=I, {Min,Max}) ->
@@ -492,8 +507,12 @@ update({test,is_eq_exact,_,[Reg,{atom,_}=Atom]}, Ts) ->
 update({test,is_record,_Fail,[Src,Tag,{integer,Arity}]}, Ts) ->
     tdb_update([{Src,{tuple,exact_size,Arity,[Tag]}}], Ts);
 
-%% Binary matching
+%% Binaries and binary matching.
 
+update({test,is_binary,_Fail,[Src]}, Ts0) ->
+    tdb_update([{Src,{binary,8}}], Ts0);
+update({test,is_bitstr,_Fail,[Src]}, Ts0) ->
+    tdb_update([{Src,{binary,1}}], Ts0);
 update({test,bs_get_integer2,_,_,Args,Dst}, Ts) ->
     tdb_update([{Dst,get_bs_integer_type(Args)}], Ts);
 update({test,bs_get_utf8,_,_,_,Dst}, Ts) ->
@@ -502,8 +521,10 @@ update({test,bs_get_utf16,_,_,_,Dst}, Ts) ->
     tdb_update([{Dst,?UNICODE_INT}], Ts);
 update({test,bs_get_utf32,_,_,_,Dst}, Ts) ->
     tdb_update([{Dst,?UNICODE_INT}], Ts);
+update({bs_init,_,{bs_init2,_,_},_,_,Dst}, Ts) ->
+    tdb_update([{Dst,{binary,8}}], Ts);
 update({bs_init,_,_,_,_,Dst}, Ts) ->
-    tdb_update([{Dst,kill}], Ts);
+    tdb_update([{Dst,{binary,1}}], Ts);
 update({bs_put,_,_,_}, Ts) ->
     Ts;
 update({bs_save2,_,_}, Ts) ->
@@ -512,12 +533,19 @@ update({bs_restore2,_,_}, Ts) ->
     Ts;
 update({bs_context_to_binary,Dst}, Ts) ->
     tdb_update([{Dst,kill}], Ts);
-update({test,bs_start_match2,_,_,_,Dst}, Ts) ->
-    tdb_update([{Dst,kill}], Ts);
-update({test,bs_get_binary2,_,_,_,Dst}, Ts) ->
-    tdb_update([{Dst,kill}], Ts);
+update({test,bs_start_match2,_,_,[Src,_],Dst}, Ts) ->
+    Type = case tdb_find(Src, Ts) of
+               {binary,_}=Type0 -> Type0;
+               _ -> {binary,1}
+           end,
+    tdb_update([{Dst,Type}], Ts);
+update({test,bs_get_binary2,_,_,[_,_,Unit,_],Dst}, Ts) ->
+    true = is_integer(Unit),                    %Assertion.
+    tdb_update([{Dst,{binary,Unit}}], Ts);
 update({test,bs_get_float2,_,_,_,Dst}, Ts) ->
     tdb_update([{Dst,float}], Ts);
+update({test,bs_test_unit,_,[Src,Unit]}, Ts) ->
+    tdb_update([{Src,{binary,Unit}}], Ts);
 
 update({test,_Test,_Fail,_Other}, Ts) ->
     Ts;
@@ -554,6 +582,7 @@ update({call_fun, _}, Ts) -> tdb_kill_xregs(Ts);
 update({apply, _}, Ts) -> tdb_kill_xregs(Ts);
 
 update({line,_}, Ts) -> Ts;
+update({'%',_}, Ts) -> Ts;
 
 %% The instruction is unknown.  Kill all information.
 update(_I, _Ts) -> tdb_new().
@@ -792,6 +821,9 @@ checkerror_2(OrigIs) -> [{set,[],[],fcheckerror}|OrigIs].
 %%%
 %%% 'integer' or {integer,{Min,Max}} that the register contains an
 %%% integer.
+%%%
+%%% {binary,Unit} means that the register contains a binary/bitstring aligned
+%%% to unit Unit.
 
 %% tdb_new() -> EmptyDataBase
 %%  Creates a new, empty type database.
@@ -917,11 +949,14 @@ merge_type_info({integer,_}=Int, integer) ->
     Int;
 merge_type_info({integer,{Min1,Max1}}, {integer,{Min2,Max2}}) ->
     {integer,{max(Min1, Min2),min(Max1, Max2)}};
+merge_type_info({binary,U1}, {binary,U2}) ->
+    {binary,max(U1, U2)};
 merge_type_info(NewType, _) ->
     verify_type(NewType),
     NewType.
 
 verify_type({atom,_}) -> ok;
+verify_type({binary,U}) when is_integer(U) -> ok;
 verify_type(boolean) -> ok;
 verify_type(integer) -> ok;
 verify_type({integer,{Min,Max}})
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl
index fe856b12b6..dfbf2aa4a0 100644
--- a/lib/compiler/test/beam_type_SUITE.erl
+++ b/lib/compiler/test/beam_type_SUITE.erl
@@ -23,7 +23,7 @@
 	 init_per_group/2,end_per_group/2,
 	 integers/1,coverage/1,booleans/1,setelement/1,cons/1,
 	 tuple/1,record_float/1,binary_float/1,float_compare/1,
-	 arity_checks/1]).
+	 arity_checks/1,elixir_binaries/1]).
 
 suite() -> [{ct_hooks,[ts_install_cth]}].
 
@@ -42,7 +42,8 @@ groups() ->
        record_float,
        binary_float,
        float_compare,
-       arity_checks
+       arity_checks,
+       elixir_binaries
       ]}].
 
 init_per_suite(Config) ->
@@ -199,5 +200,42 @@ do_tuple_arity_check(RGB) when is_tuple(RGB),
         _ -> ok
     end.
 
+elixir_binaries(_Config) ->
+    <<"foo blitzky baz">> = elixir_binary_1(<<"blitzky">>),
+    <<"foo * baz">> = elixir_binary_2($*),
+    <<7:4,755:10>> = elixir_bitstring_3(<<755:10>>),
+    ok.
+
+elixir_binary_1(Bar) when is_binary(Bar) ->
+    <<"foo ",
+      case Bar of
+          Rewrite when is_binary(Rewrite) ->
+              Rewrite;
+          Rewrite ->
+              list_to_binary(Rewrite)
+      end/binary,
+      " baz">>.
+
+elixir_binary_2(Arg) ->
+    Bin = <<Arg>>,
+    <<"foo ",
+      case Bin of
+          Rewrite when is_binary(Rewrite) ->
+              Rewrite;
+          Rewrite ->
+              list_to_binary:to_string(Rewrite)
+      end/binary,
+      " baz">>.
+
+elixir_bitstring_3(Bar) when is_bitstring(Bar) ->
+    <<7:4,
+      case Bar of
+          Rewrite when is_bitstring(Rewrite) ->
+              Rewrite;
+          Rewrite ->
+              list_to_bitstring(Rewrite)
+      end/bitstring>>.
+
+
 id(I) ->
     I.
-- 
2.16.0