summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErlang/OTP <otp@erlang.org>2020-05-20 09:57:30 +0200
committerErlang/OTP <otp@erlang.org>2020-05-20 09:57:30 +0200
commitbb6a061d36f20717be9207a10b5ed97864c1d5fe (patch)
treebb0a0406a956e88419fbc4f9c81147fd7e75b496
parent01c8f2b5638a485bc8dff172d9d581d5e2279993 (diff)
parent03ffcfd77b466ee40576f33518c51c1120f60c1a (diff)
downloaderlang-bb6a061d36f20717be9207a10b5ed97864c1d5fe.tar.gz
Merge branch 'bjorn/compiler/beam_ssa_bool/ERL-1246/OTP-16652' into maint-23
* bjorn/compiler/beam_ssa_bool/ERL-1246/OTP-16652: Fix incorrect compilation of guard expressions with 'not'
-rw-r--r--lib/compiler/src/beam_ssa_bool.erl8
-rw-r--r--lib/compiler/test/guard_SUITE.erl25
2 files changed, 30 insertions, 3 deletions
diff --git a/lib/compiler/src/beam_ssa_bool.erl b/lib/compiler/src/beam_ssa_bool.erl
index 7ae9070df2..8fb87391c5 100644
--- a/lib/compiler/src/beam_ssa_bool.erl
+++ b/lib/compiler/src/beam_ssa_bool.erl
@@ -922,9 +922,11 @@ opt_digraph_instr(#b_set{dst=Dst}=I, G0, St) ->
%% Rewriting 'xor' is not practical. Fortunately,
%% 'xor' is almost never used in practice.
not_possible();
- #b_set{op={bif,'not'},args=[#b_var{}=Bool]} ->
- G = convert_to_br_node(I, Fail, G1, St),
- redirect_test(Bool, {fail,Succ}, G, St);
+ #b_set{op={bif,'not'}} ->
+ %% This is suprisingly rare. The previous attempt to
+ %% optimize it was broken, which wasn't noticed because
+ %% very few test cases triggered this code.
+ not_possible();
#b_set{op=phi,dst=Bool} ->
Vtx = get_vertex(Bool, St),
G2 = del_out_edges(Vtx, G1),
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 4a53698e15..badbde612e 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -2300,6 +2300,7 @@ beam_bool_SUITE(_Config) ->
in_catch(),
recv_semi(),
andalso_repeated_var(),
+ erl1246(),
ok.
before_and_inside_if() ->
@@ -2597,6 +2598,30 @@ andalso_repeated_var() ->
andalso_repeated_var(B) when B andalso B -> ok;
andalso_repeated_var(_) -> error.
+-record(erl1246, {tran_stat = 0}).
+
+erl1246() ->
+ false = erl1246(#erl1246{tran_stat = 0}, #{cid => 1131}),
+ false = erl1246(#erl1246{tran_stat = 12}, #{cid => 1131}),
+ false = erl1246(#erl1246{tran_stat = 12}, #{cid => 9502}),
+ true = erl1246(#erl1246{tran_stat = 0}, #{cid => 9502}),
+ ok.
+
+erl1246(Rec, #{cid := CollID}) ->
+ {GiftCollID, _} = erl1246_conf(gift_coll),
+ IsTranStat = Rec#erl1246.tran_stat =:= erl1246_conf(transform_id),
+ if
+ %% Optimization of 'not' in a guard was broken.
+ CollID =:= GiftCollID andalso not IsTranStat ->
+ true;
+ true ->
+ false
+ end.
+
+erl1246_conf(gift_coll) -> {9502, {112, 45}};
+erl1246_conf(transform_id) -> 12;
+erl1246_conf(_) -> undefined.
+
%%%
%%% End of beam_bool_SUITE tests.
%%%