From eca5f59f979679210f754ecc48c4da26f94de832 Mon Sep 17 00:00:00 2001 From: Frej Drejhammar Date: Mon, 15 Jul 2024 15:09:21 +0200 Subject: [PATCH] compiler alias analysis: Improve handling of Phi-instructions Stop treating Phi instructions as an extraction, instead make use of the infrastructure used to derive the structure and alias status of function arguments. The sharing state database representation for the result of a Phi instruction is the same as for a function argument of a function with multiple call sites, where the concrete argument values at the call sites are the value at the respective predecessor block. --- lib/compiler/src/beam_ssa_alias.erl | 12 ++-- lib/compiler/src/beam_ssa_ss.erl | 15 +++++ .../test/beam_ssa_check_SUITE_data/phis.erl | 57 +++++++++++++++++++ 3 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 lib/compiler/test/beam_ssa_check_SUITE_data/phis.erl diff --git a/lib/compiler/src/beam_ssa_alias.erl b/lib/compiler/src/beam_ssa_alias.erl index f9602566ddc7..9da813d96ab0 100644 --- a/lib/compiler/src/beam_ssa_alias.erl +++ b/lib/compiler/src/beam_ssa_alias.erl @@ -502,7 +502,7 @@ aa_is([_I=#b_set{dst=Dst,op=Op,args=Args,anno=Anno0}|Is], SS0, AAS0) -> peek_message -> {aa_set_aliased(Dst, SS0), AAS0}; phi -> - {aa_phi(Dst, Args, SS0, AAS0), AAS0}; + aa_phi(Dst, Args, SS0, AAS0); put_list -> SS1 = beam_ssa_ss:add_var(Dst, unique, SS0), Types = @@ -1125,10 +1125,14 @@ aa_bif(Dst, Bif, Args, SS, _AAS) -> aa_set_aliased([Dst|Args], SS) end. -aa_phi(Dst, Args0, SS0, AAS) -> +aa_phi(Dst, Args0, SS0, #aas{cnt=Cnt0}=AAS) -> + %% TODO: Use type info? Args = [V || {V,_} <- Args0], - SS = aa_alias_surviving_args(Args, {phi,Dst}, SS0, AAS), - aa_derive_from(Dst, Args, SS). + ?DP("Phi~n"), + SS1 = aa_alias_surviving_args(Args, {phi,Dst}, SS0, AAS), + ?DP(" after aa_alias_surviving_args:~n~s.~n", [beam_ssa_ss:dump(SS1)]), + {SS,Cnt} = beam_ssa_ss:phi(Dst, Args, SS1, Cnt0), + {SS,AAS#aas{cnt=Cnt}}. aa_call(Dst, [#b_local{}=Callee|Args], Anno, SS0, #aas{alias_map=AliasMap,analyzed=Analyzed, diff --git a/lib/compiler/src/beam_ssa_ss.erl b/lib/compiler/src/beam_ssa_ss.erl index 088c81fcc9a2..e878f6ef7671 100644 --- a/lib/compiler/src/beam_ssa_ss.erl +++ b/lib/compiler/src/beam_ssa_ss.erl @@ -43,6 +43,7 @@ merge_in_args/3, new/0, new/3, + phi/4, prune/3, set_call_result/4, set_status/3, @@ -450,6 +451,20 @@ accumulate_edges(V, State, Edges0) -> new() -> beam_digraph:new(). +-spec phi(beam_ssa:b_var(), [beam_ssa:b_var()], + sharing_state(), non_neg_integer()) + -> sharing_state(). +phi(Dst, Args, State0, Cnt) -> + ?assert_state(State0), + ?DP("** phi **~n~s~n", [dump(State0)]), + ?DP(" dst: ~p~n", [Dst]), + ?DP(" args: ~p~n", [Args]), + Structure = foldl(fun(Arg, Acc) -> + merge_in_arg(Arg, Acc, ?ARGS_DEPTH_LIMIT, State0) + end, no_info, Args), + ?DP(" structure: ~p~n", [Structure]), + new([Dst], [Structure], Cnt, State0). + %%% %%% Throws `too_deep` if the depth of sharing state value chains %%% exceeds SS_DEPTH_LIMIT. diff --git a/lib/compiler/test/beam_ssa_check_SUITE_data/phis.erl b/lib/compiler/test/beam_ssa_check_SUITE_data/phis.erl new file mode 100644 index 000000000000..cff2b64338e2 --- /dev/null +++ b/lib/compiler/test/beam_ssa_check_SUITE_data/phis.erl @@ -0,0 +1,57 @@ +%% Extracted from lib/syntax_tools/src/erl_recomment.erl to test +%% omissions in handling of Phi instructions. + +%% ===================================================================== +%% Licensed under the Apache License, Version 2.0 (the "License"); you may +%% not use this file except in compliance with the License. You may obtain +%% a copy of the License at +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% Alternatively, you may use this file under the terms of the GNU Lesser +%% General Public License (the "LGPL") as published by the Free Software +%% Foundation; either version 2.1, or (at your option) any later version. +%% If you wish to allow use of your version of this file only under the +%% terms of the LGPL, you should delete the provisions above and replace +%% them with the notice and other provisions required by the LGPL; see +%% . If you do not delete the provisions +%% above, a recipient may use your version of this file under the terms of +%% either the Apache License or the LGPL. +%% +%% @copyright 1997-2006 Richard Carlsson +%% @author Richard Carlsson +%% @end +%% ===================================================================== + +-module(phis). + +-export([filter_forms/1]). + +-record(filter, {file = undefined :: file:filename() | 'undefined', + line = 0 :: integer()}). + +filter_forms(Fs) -> + filter_forms(Fs, #filter{}). + +filter_forms([{A1, A2} | Fs], S) -> +%ssa% (_, Rec0) when post_ssa_opt -> +%ssa% Rec = update_record(inplace, 3, Rec0, ...), +%ssa% Phi = phi({Rec0, _}, {Rec, _}), +%ssa% _ = update_record(inplace, 3, Phi, ...). + S1 = case ex:f() of + undefined -> + S#filter{file = A1, line = A2}; + _ -> + S + end, + if S1#filter.file =:= A1 -> + filter_forms(Fs, S1#filter{line = A2}); + true -> + filter_forms(Fs, S1) + end; +filter_forms([], _) -> + [].