Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
2452-compiler-Remove-eta-conversion.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 2452-compiler-Remove-eta-conversion.patch of Package erlang
From 36656399c65d7b493238860b243c2dde6397ddc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org> Date: Tue, 21 Dec 2021 22:07:09 +0100 Subject: [PATCH 2/4] compiler: Remove eta conversion This resurrects 750ecdea08fa5fa7e32b7f3019eed96c1699427e, which was removed because it made HiPE unhappy. Co-authored-by: Anthony Ramine <n.oxyde@gmail.com> --- erts/emulator/test/trace_local_SUITE.erl | 16 +-- lib/compiler/src/Makefile | 2 - lib/compiler/src/beam_dict.erl | 8 +- lib/compiler/src/beam_ssa_funs.erl | 152 ----------------------- lib/compiler/src/compile.erl | 5 - lib/compiler/src/compiler.app.src | 1 - lib/compiler/src/v3_core.erl | 2 + lib/compiler/src/v3_kernel.erl | 34 ++--- lib/compiler/test/compile_SUITE.erl | 4 +- lib/tools/test/cprof_SUITE.erl | 10 +- 10 files changed, 39 insertions(+), 195 deletions(-) delete mode 100644 lib/compiler/src/beam_ssa_funs.erl diff --git a/erts/emulator/test/trace_local_SUITE.erl b/erts/emulator/test/trace_local_SUITE.erl index 8cf8c81b7a..5913da3381 100644 --- a/erts/emulator/test/trace_local_SUITE.erl +++ b/erts/emulator/test/trace_local_SUITE.erl @@ -803,16 +803,16 @@ exception_test(Opts, Func0, Args0) -> %% Func0 and Args0 are for the innermost call, now we will %% wrap them in wrappers... {Func1,Args1} = - case Function of - true -> {fun exc/2,[Func0,Args0]}; - false -> {Func0,Args0} - end, + case Function of + true -> {fun(F, As) -> exc(F, As) end, [Func0,Args0]}; + false -> {Func0,Args0} + end, {Func,Args} = - case Apply of - true -> {{erlang,apply},[Func1,Args1]}; - false -> {Func1,Args1} - end, + case Apply of + true -> {{erlang,apply},[Func1,Args1]}; + false -> {Func1,Args1} + end, R1 = exc_slave(ExcOpts, Func, Args), Stack2 = [{?MODULE,exc_top,3,[]},{?MODULE,slave,2,[]}], diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile index 54bf9bcb1f..b7dcb275ea 100644 --- a/lib/compiler/src/Makefile +++ b/lib/compiler/src/Makefile @@ -64,7 +64,6 @@ MODULES = \ beam_ssa_bsm \ beam_ssa_codegen \ beam_ssa_dead \ - beam_ssa_funs \ beam_ssa_lint \ beam_ssa_opt \ beam_ssa_pp \ @@ -205,7 +204,6 @@ $(EBIN)/beam_ssa_bsm.beam: beam_ssa.hrl $(EBIN)/beam_ssa_bool.beam: beam_ssa.hrl $(EBIN)/beam_ssa_codegen.beam: beam_ssa.hrl $(EBIN)/beam_ssa_dead.beam: beam_ssa.hrl -$(EBIN)/beam_ssa_funs.beam: beam_ssa.hrl $(EBIN)/beam_ssa_lint.beam: beam_ssa.hrl $(EBIN)/beam_ssa_opt.beam: beam_ssa.hrl $(EBIN)/beam_ssa_pp.beam: beam_ssa.hrl diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl index f6651ae119..36bdb01df5 100644 --- a/lib/compiler/src/beam_dict.erl +++ b/lib/compiler/src/beam_dict.erl @@ -285,15 +285,17 @@ string_table(#asm{strings=Strings,string_offset=Size}) -> -spec lambda_table(bdict()) -> {non_neg_integer(), [<<_:192>>]}. -lambda_table(#asm{locals=Loc0,lambdas={NumLambdas,Lambdas0}}) -> +lambda_table(#asm{locals=Loc0,exports=Ext0,lambdas={NumLambdas,Lambdas0}}) -> Lambdas1 = sofs:relation(Lambdas0), Loc = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Loc0]), - Lambdas2 = sofs:relative_product1(Lambdas1, Loc), + Ext = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Ext0]), + All = sofs:union(Loc, Ext), + Lambdas2 = sofs:relative_product1(Lambdas1, All), %% Initialize OldUniq to 0. It will be set to an unique value %% based on the MD5 checksum of the BEAM code for the module. OldUniq = 0, Lambdas = [<<F:32,A:32,Lbl:32,Index:32,NumFree:32,OldUniq:32>> || - {{Index,Lbl,NumFree},{F,A}} <- sofs:to_external(Lambdas2)], + {{Index,Lbl,NumFree},{F,A}} <- sofs:to_external(Lambdas2)], {NumLambdas,Lambdas}. %% Returns the literal table. diff --git a/lib/compiler/src/beam_ssa_funs.erl b/lib/compiler/src/beam_ssa_funs.erl deleted file mode 100644 index a7b648bc47..0000000000 --- a/lib/compiler/src/beam_ssa_funs.erl +++ /dev/null @@ -1,152 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2018-2021. All Rights Reserved. -%% -%% 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 -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% 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. -%% -%% %CopyrightEnd% -%% - -%%% -%%% If a fun is defined locally and only used for calls, it can be replaced -%%% with direct calls to the relevant function. This greatly speeds up "named -%%% functions" (which rely on make_fun to recreate themselves) and macros that -%%% wrap their body in a fun. -%%% - --module(beam_ssa_funs). - --export([module/2]). - --include("beam_ssa.hrl"). - --import(lists, [foldl/3]). - --spec module(Module, Options) -> Result when - Module :: beam_ssa:b_module(), - Options :: [compile:option()], - Result :: {ok, beam_ssa:b_module()}. - -module(#b_module{body=Fs0}=Module, _Opts) -> - Trampolines = foldl(fun find_trampolines/2, #{}, Fs0), - Fs = [lfo(F, Trampolines) || F <- Fs0], - {ok, Module#b_module{body=Fs}}. - -%% If a function does absolutely nothing beyond calling another function with -%% the same arguments in the same order, we can shave off a call by short- -%% circuiting it. -find_trampolines(#b_function{args=Args,bs=Blocks}=F, Trampolines) -> - case map_get(0, Blocks) of - #b_blk{is=[#b_set{op=call, - args=[#b_local{}=Actual | Args], - dst=Dst}], - last=#b_ret{arg=Dst}} -> - {_, Name, Arity} = beam_ssa:get_anno(func_info, F), - Trampoline = #b_local{name=#b_literal{val=Name},arity=Arity}, - Trampolines#{Trampoline => Actual}; - _ -> - Trampolines - end. - -lfo(#b_function{bs=Blocks0}=F, Trampolines) -> - Linear0 = beam_ssa:linearize(Blocks0), - Linear = lfo_optimize(Linear0, lfo_analyze(Linear0, #{}), Trampolines), - F#b_function{bs=maps:from_list(Linear)}. - -%% Gather a map of the locally defined funs that are only used for calls. -lfo_analyze([{_L,#b_blk{is=Is,last=Last}}|Bs], LFuns0) -> - LFuns = lfo_analyze_last(Last, lfo_analyze_is(Is, LFuns0)), - lfo_analyze(Bs, LFuns); -lfo_analyze([], LFuns) -> - LFuns. - -lfo_analyze_is([#b_set{op=make_fun, - dst=Dst, - args=[#b_local{} | FreeVars]}=Def | Is], - LFuns0) -> - LFuns = maps:put(Dst, Def, maps:without(FreeVars, LFuns0)), - lfo_analyze_is(Is, LFuns); -lfo_analyze_is([#b_set{op=call, - args=[Fun | CallArgs]} | Is], - LFuns) when is_map_key(Fun, LFuns) -> - #b_set{args=[#b_local{arity=Arity} | FreeVars]} = map_get(Fun, LFuns), - case length(CallArgs) + length(FreeVars) of - Arity -> - lfo_analyze_is(Is, maps:without(CallArgs, LFuns)); - _ -> - %% This will `badarity` at runtime, and it's easier to disable the - %% optimization than to simulate it. - lfo_analyze_is(Is, maps:without([Fun | CallArgs], LFuns)) - end; -lfo_analyze_is([#b_set{args=Args} | Is], LFuns) when map_size(LFuns) =/= 0 -> - %% We disqualify funs that are used outside calls because this forces them - %% to be created anyway, and the slight performance gain from direct calls - %% is not enough to offset the potential increase in stack frame size (the - %% free variables need to be kept alive until the call). - lfo_analyze_is(Is, maps:without(Args, LFuns)); -lfo_analyze_is([_ | Is], LFuns) -> - lfo_analyze_is(Is, LFuns); -lfo_analyze_is([], LFuns) -> - LFuns. - -lfo_analyze_last(#b_switch{arg=Arg}, LFuns) -> - maps:remove(Arg, LFuns); -lfo_analyze_last(#b_ret{arg=Arg}, LFuns) -> - maps:remove(Arg, LFuns); -lfo_analyze_last(_, LFuns) -> - LFuns. - -%% Replace all calls of suitable funs with a direct call to their -%% implementation. Liveness optimization will get rid of the make_fun -%% instruction. -lfo_optimize(Linear, LFuns, _Trampolines) when map_size(LFuns) =:= 0 -> - Linear; -lfo_optimize(Linear, LFuns, Trampolines) -> - lfo_optimize_1(Linear, LFuns, Trampolines). - -lfo_optimize_1([{L,#b_blk{is=Is0}=Blk}|Bs], LFuns, Trampolines) -> - Is = lfo_optimize_is(Is0, LFuns, Trampolines), - [{L,Blk#b_blk{is=Is}} | lfo_optimize_1(Bs, LFuns, Trampolines)]; -lfo_optimize_1([], _LFuns, _Trampolines) -> - []. - -lfo_optimize_is([#b_set{op=call, - args=[Fun | CallArgs]}=Call0 | Is], - LFuns, Trampolines) when is_map_key(Fun, LFuns) -> - #b_set{args=[Local | FreeVars]} = map_get(Fun, LFuns), - Args = [lfo_short_circuit(Local, Trampolines) | CallArgs ++ FreeVars], - Call = beam_ssa:add_anno(local_fun_opt, Fun, Call0#b_set{args=Args}), - [Call | lfo_optimize_is(Is, LFuns, Trampolines)]; -lfo_optimize_is([I | Is], LFuns, Trampolines) -> - [I | lfo_optimize_is(Is, LFuns, Trampolines)]; -lfo_optimize_is([], _LFuns, _Trampolines) -> - []. - -lfo_short_circuit(Call, Trampolines) -> - lfo_short_circuit(Call, Trampolines, sets:new([{version, 2}])). - -lfo_short_circuit(Call, Trampolines, Seen0) -> - %% Beware of infinite loops! Get out if this call has been seen before. - case sets:is_element(Call, Seen0) of - true -> - Call; - false -> - case Trampolines of - #{Call := Other} -> - Seen = sets:add_element(Call, Seen0), - lfo_short_circuit(Other, Trampolines, Seen); - #{} -> - Call - end - end. diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index b65750d153..f364b56645 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -876,10 +876,6 @@ kernel_passes() -> {iff,dssabsm,{listing,"ssabsm"}}, {unless,no_bsm_opt,{iff,ssalint,{pass,beam_ssa_lint}}}, - {unless,no_fun_opt,{pass,beam_ssa_funs}}, - {iff,dssafuns,{listing,"ssafuns"}}, - {unless,no_fun_opt,{iff,ssalint,{pass,beam_ssa_lint}}}, - {unless,no_ssa_opt,{pass,beam_ssa_opt}}, {iff,dssaopt,{listing,"ssaopt"}}, {unless,no_ssa_opt,{iff,ssalint,{pass,beam_ssa_lint}}}, @@ -2054,7 +2050,6 @@ pre_load() -> beam_ssa_bsm, beam_ssa_codegen, beam_ssa_dead, - beam_ssa_funs, beam_ssa_opt, beam_ssa_pre_codegen, beam_ssa_recv, diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src index e257c8fc3a..5e8135bd1e 100644 --- a/lib/compiler/src/compiler.app.src +++ b/lib/compiler/src/compiler.app.src @@ -40,7 +40,6 @@ beam_ssa_bsm, beam_ssa_codegen, beam_ssa_dead, - beam_ssa_funs, beam_ssa_lint, beam_ssa_opt, beam_ssa_pp, diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 2223db6608..6bf87e131c 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -723,6 +723,8 @@ expr({'catch',L,E0}, St0) -> Lanno = lineno_anno(L, St1), {#icatch{anno=#a{anno=Lanno},body=Eps ++ [E1]},[],St1}; expr({'fun',L,{function,F,A}}, St0) -> + %% Generate a new name for eta conversion of local funs (`fun local/123`) + %% in case `no_shared_fun_wrappers` is given. {Fname,St1} = new_fun_name(St0), Lanno = full_anno(L, St1), Id = {0,0,Fname}, diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl index cf6df77d68..aa3fc033eb 100644 --- a/lib/compiler/src/v3_kernel.erl +++ b/lib/compiler/src/v3_kernel.erl @@ -78,10 +78,9 @@ -export([module/2,format_error/1]). -import(lists, [all/2,droplast/1,flatten/1,foldl/3,foldr/3, - map/2,mapfoldl/3,member/2, - keyfind/3,keyreplace/4, - last/1,partition/2,reverse/1, - sort/1,sort/2,splitwith/2]). + map/2,mapfoldl/3,member/2,keyfind/3,last/1, + partition/2,reverse/1,sort/1,sort/2, + splitwith/2]). -import(ordsets, [add_element/2,intersection/2, subtract/2,union/2,union/1]). @@ -234,25 +233,19 @@ gexpr_test_add(Ke, St0) -> %% expr(Cexpr, Sub, State) -> {Kexpr,[PreKexpr],State}. %% Convert a Core expression, flattening it at the same time. -expr(#c_var{anno=A0,name={Name,Arity}}=Fname, Sub, St) -> - Vs = [#c_var{name=list_to_atom("V" ++ integer_to_list(V))} || - V <- integers(1, Arity)], +expr(#c_var{anno=A,name={Name0,Arity}}=Fname, Sub, St) -> case St#kern.no_shared_fun_wrappers of false -> - %% Generate a (possibly shared) wrapper function for calling - %% this function. - Wrapper0 = ["-fun.",atom_to_list(Name),"/",integer_to_list(Arity),"-"], - Wrapper = list_to_atom(flatten(Wrapper0)), - Id = {id,{0,0,Wrapper}}, - A = keyreplace(id, 1, A0, Id), - Fun = #c_fun{anno=A,vars=Vs,body=#c_apply{anno=A,op=Fname,args=Vs}}, - expr(Fun, Sub, St); + Name = get_fsub(Name0, Arity, Sub), + {#k_local{anno=A,name=Name,arity=Arity},[],St}; true -> %% For backward compatibility with OTP 22 and earlier, %% use the pre-generated name for the fun wrapper. %% There will be one wrapper function for each occurrence %% of `fun F/A`. - Fun = #c_fun{anno=A0,vars=Vs,body=#c_apply{anno=A0,op=Fname,args=Vs}}, + Vs = [#c_var{name=list_to_atom("V" ++ integer_to_list(V))} || + V <- integers(1, Arity)], + Fun = #c_fun{anno=A,vars=Vs,body=#c_apply{anno=A,op=Fname,args=Vs}}, expr(Fun, Sub, St) end; expr(#c_var{anno=A,name=V}, Sub, St) -> @@ -1991,6 +1984,15 @@ uexpr(#ifun{anno=A,vars=Vs,body=B0}, {break,Rs}, St0) -> args=[Local|Fvs], ret=Rs}, Free,add_local_function(Fun, St)}; +uexpr(#k_local{anno=A,name=Name,arity=Arity}, {break,Rs}, St) -> + Free = lit_list_vars(get_free(Name, Arity, St)), + Fvs = make_vars(Free), + FreeCount = length(Fvs), + Bif = #k_bif{anno=A, + op=#k_internal{name=make_fun,arity=FreeCount+1}, + args=[#k_local{name=Name,arity=Arity+FreeCount} | Fvs], + ret=Rs}, + {Bif,Free,St}; uexpr(#k_letrec_goto{anno=A,first=F0,then=T0}=MatchAlt, Br, St0) -> Rs = break_rets(Br), {F1,Fu,St1} = ubody(F0, Br, St0), diff --git a/lib/tools/test/cprof_SUITE.erl b/lib/tools/test/cprof_SUITE.erl index 8eb7476f57..d27371414a 100644 --- a/lib/tools/test/cprof_SUITE.erl +++ b/lib/tools/test/cprof_SUITE.erl @@ -203,9 +203,8 @@ on_load_test(Config) -> N2 = cprof:pause(), {Module,0,[]} = cprof:analyse(Module), M4__4 = M*4 - 4, - M10_7 = M*10 - 7, - {?MODULE,M10_7,[{{?MODULE,succ,1},M4__4}, - {{?MODULE,'-fun.succ/1-',1},M4__4}, + M6_3 = M*6 - 3, + {?MODULE,M6_3,[{{?MODULE,succ,1},M4__4}, {{?MODULE,seq_r,4},M}, {{?MODULE,seq,3},M}, {{?MODULE,seq_r,3},1}]} @@ -234,11 +233,10 @@ modules_test(Config) -> N = cprof:pause(), Lr = lists:reverse(L), M4_4 = M*4 - 4, - M10_7 = M*10 - 7, + M6_3 = M*6 - 3, M2__1 = M*2 + 1, {Tot,ModList} = cprof:analyse(), - {value,{?MODULE,M10_7,[{{?MODULE,succ,1},M4_4}, - {{?MODULE,'-fun.succ/1-',1},M4_4}, + {value,{?MODULE,M6_3,[{{?MODULE,succ,1},M4_4}, {{?MODULE,seq_r,4},M}, {{?MODULE,seq,3},M}, {{?MODULE,seq_r,3},1}]}} = -- 2.31.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor