aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler/src')
-rw-r--r--lib/compiler/src/beam_ssa_pre_codegen.erl6
-rw-r--r--lib/compiler/src/beam_ssa_share.erl8
2 files changed, 11 insertions, 3 deletions
diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl
index a2e687930b..7ef604d444 100644
--- a/lib/compiler/src/beam_ssa_pre_codegen.erl
+++ b/lib/compiler/src/beam_ssa_pre_codegen.erl
@@ -1472,10 +1472,14 @@ find_loop_exit([L1,L2|_Ls], Blocks) ->
find_loop_exit_1(Path1, cerl_sets:from_list(Path2));
find_loop_exit(_, _) -> none.
+find_loop_exit_1([?BADARG_BLOCK | T], OtherPath) ->
+ %% ?BADARG_BLOCK is a marker and not an actual block, so we can't consider
+ %% it to be a common block even if both paths cross it.
+ find_loop_exit_1(T, OtherPath);
find_loop_exit_1([H|T], OtherPath) ->
case cerl_sets:is_element(H, OtherPath) of
true -> H;
- false -> find_loop_exit_1(T, OtherPath)
+ false -> find_loop_exit_1(T, OtherPath)
end;
find_loop_exit_1([], _) -> none.
diff --git a/lib/compiler/src/beam_ssa_share.erl b/lib/compiler/src/beam_ssa_share.erl
index 426efa2cc9..73983bd34a 100644
--- a/lib/compiler/src/beam_ssa_share.erl
+++ b/lib/compiler/src/beam_ssa_share.erl
@@ -303,8 +303,12 @@ canonical_is([#b_ret{arg=Arg}], VarMap, Acc0) ->
Acc0
end,
{{ret,canonical_arg(Arg, VarMap),Acc1},VarMap};
-canonical_is([#b_br{bool=#b_var{},fail=Fail}], VarMap, Acc) ->
- {{br,succ,Fail,Acc},VarMap};
+canonical_is([#b_br{bool=#b_var{}=Arg,fail=Fail}], VarMap, Acc) ->
+ %% A previous buggy version of this code omitted the canonicalized
+ %% argument in the return value. Unfortunately, that worked most
+ %% of the time, except when `br` terminator referenced a variable
+ %% defined in a previous block instead of in the same block.
+ {{br,canonical_arg(Arg, VarMap),succ,Fail,Acc},VarMap};
canonical_is([#b_br{succ=Succ}], VarMap, Acc) ->
{{br,Succ,Acc},VarMap};
canonical_is([], VarMap, Acc) ->