File 3361-Enhance-the-optimization-of-the-try-catch-eliminatio.patch of Package erlang
From 1cfeca84ac84b549e9a7b3668316dbb3c5e783d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Tue, 2 Mar 2021 08:41:13 +0100
Subject: [PATCH] Enhance the optimization of the try/catch elimination
optimization
The `beam_ssa_opt:ssa_opt_try/1` optimization would sometimes fail to
eliminate a redundant `try`/`catch` construct because it only looked
for `new_try_tag` instructions at the beginning of an SSA block. Here
is an example:
foobar({Anno}=T, V) ->
try
setelement(1, T, V)
catch
_Class:_Error:_Stack ->
Anno
end.
In the SSA code, the `get_tuple_element` instruction from the tuple
matching in the function head is at the beginning of the block with the
`new_try_tag` instruction:
8:
_10 = get_tuple_element _0, `0`
@ssa_catch_tag = new_try_tag `'try'`
br @ssa_catch_tag, ^6, ^5
Generalize the optimization to handle this example. While at it,
also make the optimization run faster by eliminating redundant
set update operations.
---
lib/compiler/src/beam_ssa_opt.erl | 56 ++++++++++++++++++-------------
1 file changed, 33 insertions(+), 23 deletions(-)
diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl
index 165330cfff..1369445e5b 100644
--- a/lib/compiler/src/beam_ssa_opt.erl
+++ b/lib/compiler/src/beam_ssa_opt.erl
@@ -1494,35 +1494,45 @@ reduce_try_is([], Acc) ->
%% unreachable landing pads, removing them from the set whenever we see a
%% branch to that block. When we encounter a `new_try_tag` instruction that
%% references a block in the unreachable set, we'll remove the try/catch.
-trim_try([{L, #b_blk{is=[#b_set{op=new_try_tag,dst=Tag}],
- last=Last0}=Blk0} | Bs],
- Unreachable0, Killed0, Acc) ->
- #b_br{succ=SuccLbl,fail=PadLbl} = Last0,
- case sets:is_element(PadLbl, Unreachable0) of
- true ->
- %% The landing pad can't be reached in any way, remove the entire
- %% try/catch.
- Blk = Blk0#b_blk{is=[],
- last=#b_br{bool=#b_literal{val=true},
- succ=SuccLbl,fail=SuccLbl}},
-
- Unreachable = sets:del_element(PadLbl, Unreachable0),
- Killed = sets:add_element(Tag, Killed0),
- trim_try(Bs, Unreachable, Killed, [{L, Blk} | Acc]);
- false ->
- trim_try(Bs, Unreachable0, Killed0, [{L, Blk0} | Acc])
- end;
trim_try([{L, #b_blk{is=[#b_set{op=landingpad} | _]}=Blk}| Bs],
Unreachable0, Killed, Acc) ->
Unreachable1 = sets:add_element(L, Unreachable0),
-
Successors = sets:from_list(beam_ssa:successors(Blk)),
Unreachable = sets:subtract(Unreachable1, Successors),
trim_try(Bs, Unreachable, Killed, [{L, Blk} | Acc]);
-trim_try([{L, Blk} | Bs], Unreachable0, Killed, Acc) ->
- Successors = sets:from_list(beam_ssa:successors(Blk)),
- Unreachable = sets:subtract(Unreachable0, Successors),
- trim_try(Bs, Unreachable, Killed, [{L, Blk} | Acc]);
+trim_try([{L, #b_blk{last=#b_ret{}}=Blk} | Bs], Unreachable, Killed, Acc) ->
+ %% Nothing to update and nothing to optimize.
+ trim_try(Bs, Unreachable, Killed, [{L,Blk}|Acc]);
+trim_try([{L, Blk0} | Bs], Unreachable0, Killed0, Acc) ->
+ case sets:is_empty(Unreachable0) of
+ true ->
+ %% Nothing to update and nothing to optimize.
+ trim_try(Bs, Unreachable0, Killed0, [{L,Blk0}|Acc]);
+ false ->
+ #b_blk{is=Is0,last=Last0} = Blk0,
+ case reverse(Is0) of
+ [#b_set{op=new_try_tag,dst=Tag}|Is] ->
+ #b_br{succ=SuccLbl,fail=PadLbl} = Last0,
+ Unreachable = sets:del_element(PadLbl, Unreachable0),
+ case sets:is_element(PadLbl, Unreachable0) of
+ true ->
+ %% The landing pad can't be reached in any way,
+ %% remove the entire try/catch.
+ Blk = Blk0#b_blk{is=reverse(Is),
+ last=#b_br{bool=#b_literal{val=true},
+ succ=SuccLbl,fail=SuccLbl}},
+ Killed = sets:add_element(Tag, Killed0),
+ trim_try(Bs, Unreachable, Killed, [{L,Blk}|Acc]);
+ false ->
+ trim_try(Bs, Unreachable, Killed0, [{L,Blk0}|Acc])
+ end;
+ _ ->
+ %% Update the set of unreachable landing_pad blocks.
+ Successors = sets:from_list(beam_ssa:successors(Blk0)),
+ Unreachable = sets:subtract(Unreachable0, Successors),
+ trim_try(Bs, Unreachable, Killed0, [{L,Blk0}|Acc])
+ end
+ end;
trim_try([], _Unreachable, Killed, Acc0) ->
case sets:is_empty(Killed) of
true ->
--
2.26.2