Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compiler: Change some bifs to guard bifs in try/catch #9042

Conversation

lucioleKi
Copy link
Contributor

@lucioleKi lucioleKi commented Nov 11, 2024

When put in a try, calling a guard bif with no side-effects is already optimized to remove the try/catch. However, there are bifs with side-effects that can be safely optimized in the same way in order to gain performance.

Example code:

try binary_to_atom(A, utf8)
    catch _:_ -> []
    end.

Before, SSA for the bif call after optimizations:

_6 = call (`erlang`:`binary_to_atom`/2), _0, `utf8`
_14 = succeeded:body _6

Now, SSA for the bif call after optimizations:

_6 = bif:binary_to_atom _0, `utf8`
_14 = succeeded:guard _6

Bifs that are optimized for try/catch in this change: binary_to_atom/1, binary_to_atom/2, binary_to_existing_atom/1, binary_to_existing_atom/2, list_to_atom/1, list_to_existing_atom/1.

@lucioleKi lucioleKi added team:VM Assigned to OTP team VM testing currently being tested, tag is used by OTP internal CI labels Nov 11, 2024
@lucioleKi lucioleKi requested review from bjorng and jhogberg November 11, 2024 09:22
@lucioleKi lucioleKi self-assigned this Nov 11, 2024
Copy link
Contributor

github-actions bot commented Nov 11, 2024

CT Test Results

No tests were run for this PR. This is either because the build failed, or the PR is based on a branch without GH actions tests configured.

Results for commit ad10c97

To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass.

See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally.

Artifacts

// Erlang/OTP Github Action Bot

@lucioleKi lucioleKi force-pushed the isabell/compiler/change-some-bifs-to-guard-bifs/OTP-19339 branch from 51eea9a to d02498c Compare November 11, 2024 09:23
@lucioleKi lucioleKi force-pushed the isabell/compiler/change-some-bifs-to-guard-bifs/OTP-19339 branch 2 times, most recently from 5446359 to b8e73f9 Compare November 11, 2024 13:37
arity=A}=R0|Args0]}=I0|Is],
Acc) ->
%% Rewrite binary_to_atom/1 call to binary_to_atom/2.
{I1, Args1} = if {M, F, A} =:= {erlang, binary_to_atom, 1} ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the same be done for binary_to_existing_atom?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, thanks for pointing out!

@michalmuskala
Copy link
Contributor

What's the criteria to tell if a BIF can or cannot be optimised in this way?

@lucioleKi
Copy link
Contributor Author

lucioleKi commented Nov 11, 2024

What's the criteria to tell if a BIF can or cannot be optimised in this way?

A BIF can be optimized this way if it's pure (i.e. does not change the state). If it's not pure, it's not always safe to remove the try/catch around it.
For this PR, we picked the 6 specific BIFs because optimizing them is safe with relatively little changes. This PR's approach cannot optimize all pure BIFs though. We would aim to optimize all pure BIFs in the future.

Edit: Apparently I failed to count for binary_to_existing_atom/1. 6 BIFs were optimized.

@lucioleKi lucioleKi force-pushed the isabell/compiler/change-some-bifs-to-guard-bifs/OTP-19339 branch 2 times, most recently from 6edf639 to 19834c0 Compare November 11, 2024 21:23
When put in a try, calling a guard bif with no side-effects is already
optimized to remove the try/catch. However, there are bifs with side-effects
that can be safely optimized in the same way in order to gain performance.

Example code:

    try binary_to_atom(A, utf8)
        catch _:_ -> []
        end.

Before, SSA for the bif call after optimizations:

    _6 = call (`erlang`:`binary_to_atom`/2), _0, `utf8`
    _14 = succeeded:body _6

Now, SSA for the bif call after optimizations:

    _6 = bif:binary_to_atom _0, `utf8`
    _14 = succeeded:guard _6

Bifs that are optimized for try/catch in this change: `binary_to_atom/1`,
`binary_to_atom/2`, `binary_to_existing_atom/1`, `binary_to_existing_atom/2`,
`list_to_atom/1`, `list_to_existing_atom/1`.
@lucioleKi lucioleKi force-pushed the isabell/compiler/change-some-bifs-to-guard-bifs/OTP-19339 branch from 19834c0 to ad10c97 Compare November 13, 2024 11:08
@lucioleKi lucioleKi merged commit 2ace9d3 into erlang:master Nov 13, 2024
21 checks passed
lucioleKi added a commit to lucioleKi/otp that referenced this pull request Nov 22, 2024
When put in a try, calling a guard bif with no side-effects and 6 other
bifs ([PR-9042](erlang#9042)) are optimized
to remove the try/catch. However, most pure bifs can be safely optimized
in the same way in order to gain performance. This PR introduces a new
internal instruction `call_pseudo_guard_bif` that enables the compiler
to remove the try/catch around the bif. The instruction is designed to
call the bif in the same way, but having more optimized error-handling
in the runtime system.

Example code:

    try float_to_list(A, utf8)
    catch _:_ -> error
    end.

Before, assembly for the bif call after optimizations:

    {label,2}.
    {allocate,1,1}.
    {'try',{y,0},{f,3}}.
    {line,[{location,"zlc.erl",23}]}.
    {call_ext,1,{extfunc,erlang,float_to_list,1}}.
    {try_end,{y,0}}.
    {deallocate,1}.
    return.

Now, assembly for the bif call after optimizations:

    {label,2}.
    {allocate,0,1}.
    {line,[{location,"zlc.erl",23}]}.
    {call_pseudo_guard_bif,1,{extfunc,erlang,float_to_list,1},{f,3}}.
    {deallocate,0}.
    return.

Bifs that are optimized for try/catch in this change are listed in
`pbif.tab`.
lucioleKi added a commit to lucioleKi/otp that referenced this pull request Nov 27, 2024
This is a fix for [PR-9042](erlang#9042).
`binary_to_atom/1` and `binary_to_existing_atom/1` now use the correct
optimization. Tests for SSA in `non_throwing_bifs.erl` are fixed and
added to the correct suite.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
team:VM Assigned to OTP team VM testing currently being tested, tag is used by OTP internal CI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants