From 7e2e56dd1e1fa73eba7db7ef13af9a89f724103c Mon Sep 17 00:00:00 2001 From: lucioleKi Date: Wed, 27 Nov 2024 14:59:35 +0100 Subject: [PATCH] compiler: Fix optimization for binary_to_atom and tests This is a fix for [PR-9042](https://github.com/erlang/otp/pull/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. --- lib/compiler/src/beam_ssa.erl | 2 + lib/compiler/test/beam_ssa_check_SUITE.erl | 9 ++- .../non_throwing_bifs.erl | 23 ++++-- lib/compiler/test/bif_SUITE.erl | 75 +++++++++++++++---- 4 files changed, 84 insertions(+), 25 deletions(-) diff --git a/lib/compiler/src/beam_ssa.erl b/lib/compiler/src/beam_ssa.erl index 1773ada4b458..9c84d963634b 100644 --- a/lib/compiler/src/beam_ssa.erl +++ b/lib/compiler/src/beam_ssa.erl @@ -239,7 +239,9 @@ no_side_effect(#b_set{op=Op}) -> can_be_guard_bif(M, F, A) -> case {M,F,A} of + {erlang, binary_to_atom, 1} -> true; {erlang, binary_to_atom, 2} -> true; + {erlang, binary_to_existing_atom, 1} -> true; {erlang, binary_to_existing_atom, 2} -> true; {erlang, list_to_atom, 1} -> true; {erlang, list_to_existing_atom, 1} -> true; diff --git a/lib/compiler/test/beam_ssa_check_SUITE.erl b/lib/compiler/test/beam_ssa_check_SUITE.erl index b1ddcb93492a..eb5a834864af 100644 --- a/lib/compiler/test/beam_ssa_check_SUITE.erl +++ b/lib/compiler/test/beam_ssa_check_SUITE.erl @@ -37,7 +37,8 @@ private_append_checks/1, ret_annotation_checks/1, sanity_checks/1, - tuple_inplace_checks/1]). + tuple_inplace_checks/1, + non_throwing_bifs/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -54,7 +55,8 @@ groups() -> private_append_checks, ret_annotation_checks, sanity_checks, - tuple_inplace_checks]}, + tuple_inplace_checks, + non_throwing_bifs]}, {post_ssa_opt_dynamic,test_lib:parallel(), [bs_size_unit_checks]}]. @@ -125,6 +127,9 @@ ret_annotation_checks(Config) when is_list(Config) -> sanity_checks(Config) when is_list(Config) -> run_post_ssa_opt(sanity_checks, Config). +non_throwing_bifs(Config) when is_list(Config) -> + run_post_ssa_opt(non_throwing_bifs, Config). + dynamic_workdir(Config) -> PrivDir = proplists:get_value(priv_dir, Config), filename:join(PrivDir, "dynamic"). diff --git a/lib/compiler/test/beam_ssa_check_SUITE_data/non_throwing_bifs.erl b/lib/compiler/test/beam_ssa_check_SUITE_data/non_throwing_bifs.erl index 571a7b1972c6..bb7d2a48931d 100644 --- a/lib/compiler/test/beam_ssa_check_SUITE_data/non_throwing_bifs.erl +++ b/lib/compiler/test/beam_ssa_check_SUITE_data/non_throwing_bifs.erl @@ -24,25 +24,32 @@ -export([try_bif1/1, try_bif2/2, try_bif3/1]). try_bif1(B) -> -%ssa% () when post_ssa_opt -> -%ssa% X = bif:binary_to_atom(B), -%ssa% _ = succeeded:guard(X). +%ssa% (B) when post_ssa_opt -> +%ssa% X = bif:binary_to_atom(B, utf8), +%ssa% Y = succeeded:guard(X), +%ssa% ret(X). try binary_to_atom(B) catch _:_ -> [] end. try_bif2(A, B) -> -%ssa% () when post_ssa_opt -> +%ssa% (A, B) when post_ssa_opt -> %ssa% X = bif:binary_to_atom(A, B), -%ssa% _ = succeeded:guard(X). +%ssa% Y = succeeded:guard(X), +%ssa% ret(X). try binary_to_atom(A, B) catch _:_ -> [] end. try_bif3(A) -> -%ssa% () when post_ssa_opt -> -%ssa% X = erlang:float_to_list(A), -%ssa% _ = succeeded:body(X). +%ssa% (A) when post_ssa_opt -> +%ssa% X = call(fun erlang:float_to_list/1, A), +%ssa% Y = succeeded:body(X), +%ssa% br(Y, Succ, Fail), +%ssa% label Succ, +%ssa% ret(X), +%ssa% label Fail, +%ssa% ret([]). try float_to_list(A) catch _:_ -> [] end. diff --git a/lib/compiler/test/bif_SUITE.erl b/lib/compiler/test/bif_SUITE.erl index 24cc12d7cf11..86758ebbbf18 100644 --- a/lib/compiler/test/bif_SUITE.erl +++ b/lib/compiler/test/bif_SUITE.erl @@ -295,23 +295,68 @@ num_clamped_add(A) -> min(max(A, 0), 10) + 100. non_throwing(_Config) -> - a = try binary_to_atom(<<"a">>) - catch _:_ -> [] - end, - l = try list_to_existing_atom([108]) - catch _:_ -> [] - end, - [] = try list_to_existing_atom([a]) - catch _:_ -> [] - end, - 'Erlang' = try binary_to_atom(<<"Erlang">>, unicode) - catch _:_ -> [] - end, - [] = try binary_to_existing_atom(a, unicode) - catch _:_ -> [] - end, + abc = thing_to_atom(~"abc"), + [] = thing_to_atom(a), + [] = thing_to_atom(42), + [] = thing_to_atom([a,b,c]), + erlang = thing_to_existing_atom(~"erlang"), + [] = thing_to_existing_atom(~"not an existing atom"), + [] = thing_to_existing_atom(a), ok. +thing_to_atom(Bin0) -> + Bin = id(Bin0), + Res = try + binary_to_atom(Bin) + catch + _:_ -> + [] + end, + Res = try + binary_to_atom(Bin, utf8) + catch + _:_ -> + [] + end, + if + is_atom(Res) -> + List = unicode:characters_to_list(Bin), + Res = try + list_to_atom(List) + catch + _:_ -> + [] + end; + true -> + Res + end. +thing_to_existing_atom(Bin0) -> + Bin = id(Bin0), + Res = try + binary_to_existing_atom(Bin) + catch + _:_ -> + [] + end, + Res = try + binary_to_existing_atom(Bin, utf8) + catch + _:_ -> + [] + end, + if + is_atom(Res) -> + List = unicode:characters_to_list(Bin), + Res = try + list_to_existing_atom(List) + catch + _:_ -> + [] + end; + true -> + Res + end. + %%% %%% Common utilities. %%%