diff options
author | Björn Gustavsson <[email protected]> | 2017-10-06 09:06:24 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2017-10-11 09:59:41 +0200 |
commit | 34c8b06de52ac81e2938e93ed7a219d7611c16f9 (patch) | |
tree | 0ed2df8a4aa99368ee5bf483c056cf808d34fd25 /lib/hipe | |
parent | 4fe3f3b8be4825726fab6d4ea7515adf5b5df1ac (diff) | |
download | otp-34c8b06de52ac81e2938e93ed7a219d7611c16f9.tar.gz otp-34c8b06de52ac81e2938e93ed7a219d7611c16f9.tar.bz2 otp-34c8b06de52ac81e2938e93ed7a219d7611c16f9.zip |
Optimize try/catch that ignores the return value
If a try/catch is used to ignore the potential exception caused by some
expression with a side effect such as:
try
side_effect()
catch _Class:_Reason ->
ok
end,
.
.
.
the generated code will be wasteful:
try YReg TryLabel
%% call side_effect() here
try_end Yreg
jump GoodLabel
TryLabel:
try_case YReg
%% try_case has set up registers as follows:
%% x(0) -> error | exit | throw
%% x(1) -> reason
%% x(2) -> raw stack trace data
GoodLabel:
%% This code does not use any x registers.
There will be two code paths that both end up at GoodLabel, and
the try_case instruction will set up registers that are never used.
We can do better by replacing try_case with try_end to obtain this
code:
try YReg TryLabel
%% call side_effect() here
try_end Yreg
jump GoodLabel
TryLabel:
try_end YReg
GoodLabel:
The jump optimizer (beam_jump) can further optimize this code
like this:
try YReg TryLabel
%% call side_effect() here
TryLabel:
try_end YReg
Diffstat (limited to 'lib/hipe')
-rw-r--r-- | lib/hipe/icode/hipe_beam_to_icode.erl | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl index 2abecf7f18..167f5c67bb 100644 --- a/lib/hipe/icode/hipe_beam_to_icode.erl +++ b/lib/hipe/icode/hipe_beam_to_icode.erl @@ -2296,6 +2296,12 @@ split_code([First|Code], Label, Instr) -> split_code([Instr|Code], Label, Instr, Prev, As) when Prev =:= Label -> split_code_final(Code, As); % drop both label and instruction +split_code([{icode_end_try}|_]=Code, Label, {try_case,_}, Prev, As) + when Prev =:= Label -> + %% The try_case has been replaced with try_end as an optimization. + %% Keep this instruction, since it might be the only try_end instruction + %% for this try/catch block. + split_code_final(Code, As); % drop label split_code([Other|_Code], Label, Instr, Prev, _As) when Prev =:= Label -> ?EXIT({missing_instr_after_label, Label, Instr, [Other, Prev | _As]}); split_code([Other|Code], Label, Instr, Prev, As) -> |