File 2071-beam_ssa_opt-Do-more-strength-reduction-in-ssa_opt_l.patch of Package erlang

From c6a806eee17fbf9ff60b34acfe464b38e988128a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Tue, 26 May 2020 09:41:29 +0200
Subject: [PATCH 1/3] beam_ssa_opt: Do more strength reduction in ssa_opt_live

---
 lib/compiler/src/beam_ssa_opt.erl | 37 ++++++++++++++++++++++---------
 lib/compiler/test/map_SUITE.erl   | 13 +++++++++++
 2 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl
index d77b7756e8..3c8f409e0b 100644
--- a/lib/compiler/src/beam_ssa_opt.erl
+++ b/lib/compiler/src/beam_ssa_opt.erl
@@ -1342,23 +1342,38 @@ live_opt_is([#b_set{op=phi,dst=Dst}=I|Is], Live, Acc) ->
         false ->
             live_opt_is(Is, Live, Acc)
     end;
-live_opt_is([#b_set{op={succeeded,_},dst=SuccDst,args=[MapDst]}=SuccI,
-             #b_set{op=get_map_element,dst=MapDst}=MapI | Is],
+live_opt_is([#b_set{op={succeeded,guard},dst=SuccDst,args=[Dst]}=SuccI,
+             #b_set{op=Op,dst=Dst}=I0|Is],
             Live0, Acc) ->
     case {gb_sets:is_member(SuccDst, Live0),
-          gb_sets:is_member(MapDst, Live0)} of
+          gb_sets:is_member(Dst, Live0)} of
         {true, true} ->
             Live = gb_sets:delete(SuccDst, Live0),
-            live_opt_is([MapI | Is], Live, [SuccI | Acc]);
+            live_opt_is([I0|Is], Live, [SuccI|Acc]);
         {true, false} ->
-            %% 'get_map_element' is unused; replace 'succeeded' with
-            %% 'has_map_field'
-            NewI = MapI#b_set{op=has_map_field,dst=SuccDst},
-            live_opt_is([NewI | Is], Live0, Acc);
+            %% The result of the instruction before {succeeded,guard} is
+            %% unused. Attempt to perform a strength reduction.
+            case Op of
+                {bif,'not'} ->
+                    I = I0#b_set{op={bif,is_boolean},dst=SuccDst},
+                    live_opt_is([I|Is], Live0, Acc);
+                {bif,tuple_size} ->
+                    I = I0#b_set{op={bif,is_tuple},dst=SuccDst},
+                    live_opt_is([I|Is], Live0, Acc);
+                bs_start_match ->
+                    [#b_literal{val=new},Bin] = I0#b_set.args,
+                    I = I0#b_set{op={bif,is_bitstring},args=[Bin],dst=SuccDst},
+                    live_opt_is([I|Is], Live0, Acc);
+                get_map_element ->
+                    I = I0#b_set{op=has_map_field,dst=SuccDst},
+                    live_opt_is([I|Is], Live0, Acc);
+                _ ->
+                    Live1 = gb_sets:delete(SuccDst, Live0),
+                    Live = gb_sets:add(Dst, Live1),
+                    live_opt_is([I0|Is], Live, [SuccI|Acc])
+            end;
         {false, true} ->
-            %% 'succeeded' is unused (we know it will succeed); discard it and
-            %% keep 'get_map_element'
-            live_opt_is([MapI | Is], Live0, Acc);
+            live_opt_is([I0|Is], Live0, Acc);
         {false, false} ->
             live_opt_is(Is, Live0, Acc)
     end;
diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl
index 3c5c6214bc..d0455877f5 100644
--- a/lib/compiler/test/map_SUITE.erl
+++ b/lib/compiler/test/map_SUITE.erl
@@ -1263,6 +1263,10 @@ t_guard_bifs(Config) when is_list(Config) ->
     true   = map_is_key_head_not(#{}),
     false  = map_is_key_head_not(not_a_map),
 
+    b = map_get_head_badmap1(),
+    b = map_get_head_badmap2(),
+    b = map_get_head_badmap3(),
+
     true   = map_guard_body(#{a=>1}),
     false  = map_guard_body({}),
     true   = map_guard_pattern(#{a=>1, <<"hi">> => "hi" }),
@@ -1337,6 +1341,15 @@ map_get_head(_) -> false.
 map_get_head_not(M) when not map_get(a, M) -> true;
 map_get_head_not(_) -> false.
 
+map_get_head_badmap1() when map_get(key, not_a_map), false -> a;
+map_get_head_badmap1() -> b.
+
+map_get_head_badmap2() when map_get(key, not_a_map), true -> a;
+map_get_head_badmap2() -> b.
+
+map_get_head_badmap3() when map_get(key, not_a_map) -> a;
+map_get_head_badmap3() -> b.
+
 map_is_key_head(M) when is_map_key(a, M) -> true;
 map_is_key_head(_) -> false.
 
-- 
2.26.2

openSUSE Build Service is sponsored by