aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/beam_ssa_opt.erl
diff options
context:
space:
mode:
authorJohn Högberg <[email protected]>2019-01-21 07:25:47 +0100
committerJohn Högberg <[email protected]>2019-01-24 08:37:37 +0100
commit294d66a295f6c2101fe3c2da630979ad4e736c08 (patch)
tree7a74227c185c69a976bd90b521eddd47d01db5d3 /lib/compiler/src/beam_ssa_opt.erl
parent1c73a313e72909d054f55e321c1929d2be55ff11 (diff)
downloadotp-294d66a295f6c2101fe3c2da630979ad4e736c08.tar.gz
otp-294d66a295f6c2101fe3c2da630979ad4e736c08.tar.bz2
otp-294d66a295f6c2101fe3c2da630979ad4e736c08.zip
compiler: Introduce module-level type optimization
This commit lets the type optimization pass work across functions, tracking return and argument types to eliminate redundant tests.
Diffstat (limited to 'lib/compiler/src/beam_ssa_opt.erl')
-rw-r--r--lib/compiler/src/beam_ssa_opt.erl32
1 files changed, 22 insertions, 10 deletions
diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl
index 93c5922547..3685c09a2b 100644
--- a/lib/compiler/src/beam_ssa_opt.erl
+++ b/lib/compiler/src/beam_ssa_opt.erl
@@ -39,7 +39,7 @@
-include("beam_ssa_opt.hrl").
--import(lists, [append/1,foldl/3,keyfind/3,member/2,
+-import(lists, [append/1,duplicate/2,foldl/3,keyfind/3,member/2,
reverse/1,reverse/2,
splitwith/2,sort/1,takewhile/2,unzip/1]).
@@ -146,8 +146,8 @@ prologue_passes(Opts) ->
?PASS(ssa_opt_linearize),
?PASS(ssa_opt_tuple_size),
?PASS(ssa_opt_record),
- ?PASS(ssa_opt_cse) %Helps the first type pass.
- ],
+ ?PASS(ssa_opt_cse), %Helps the first type pass.
+ ?PASS(ssa_opt_type_start)],
passes_1(Ps, Opts).
%% These passes all benefit from each other (in roughly this order), so they
@@ -157,12 +157,13 @@ repeated_passes(Opts) ->
?PASS(ssa_opt_bs_puts),
?PASS(ssa_opt_dead),
?PASS(ssa_opt_cse),
- ?PASS(ssa_opt_type)], %Must run after ssa_opt_dead to
+ ?PASS(ssa_opt_type_continue)], %Must run after ssa_opt_dead to
%clean up phi nodes.
passes_1(Ps, Opts).
epilogue_passes(Opts) ->
- Ps = [?PASS(ssa_opt_float),
+ Ps = [?PASS(ssa_opt_type_finish),
+ ?PASS(ssa_opt_float),
?PASS(ssa_opt_live), %One last time to clean up the
%mess left by the float pass.
?PASS(ssa_opt_bsm),
@@ -199,18 +200,21 @@ build_func_db(#b_module{body=Fs,exports=Exports}) ->
throw:load_nif -> #{}
end.
-fdb_1([#b_function{ bs=Bs }=F | Fs], Exports, FuncDb0) ->
+fdb_1([#b_function{ args=Args,bs=Bs }=F | Fs], Exports, FuncDb0) ->
Id = get_func_id(F),
#b_local{name=#b_literal{val=Name}, arity=Arity} = Id,
Exported = gb_sets:is_element({Name, Arity}, Exports),
+ ArgTypes = duplicate(length(Args), #{}),
FuncDb1 = case FuncDb0 of
%% We may have an entry already if someone's called us.
#{ Id := Info } ->
- FuncDb0#{ Id := Info#func_info{ exported=Exported }};
+ FuncDb0#{ Id := Info#func_info{ exported=Exported,
+ arg_types=ArgTypes }};
#{} ->
- FuncDb0#{ Id => #func_info{ exported=Exported }}
+ FuncDb0#{ Id => #func_info{ exported=Exported,
+ arg_types=ArgTypes }}
end,
FuncDb = beam_ssa:fold_rpo(fun(_L, #b_blk{is=Is}, FuncDb) ->
@@ -293,10 +297,18 @@ ssa_opt_dead({#st{ssa=Linear}=St, FuncDb}) ->
ssa_opt_linearize({#st{ssa=Blocks}=St, FuncDb}) ->
{St#st{ssa=beam_ssa:linearize(Blocks)}, FuncDb}.
-ssa_opt_type({#st{ssa=Linear0,args=Args}=St0, FuncDb}) ->
- Linear = beam_ssa_type:opt(Linear0, Args),
+ssa_opt_type_start({#st{ssa=Linear0,args=Args,anno=Anno}=St0, FuncDb0}) ->
+ {Linear, FuncDb} = beam_ssa_type:opt_start(Linear0, Args, Anno, FuncDb0),
{St0#st{ssa=Linear}, FuncDb}.
+ssa_opt_type_continue({#st{ssa=Linear0,args=Args,anno=Anno}=St0, FuncDb0}) ->
+ {Linear, FuncDb} = beam_ssa_type:opt_continue(Linear0, Args, Anno, FuncDb0),
+ {St0#st{ssa=Linear}, FuncDb}.
+
+ssa_opt_type_finish({#st{args=Args,anno=Anno0}=St0, FuncDb0}) ->
+ {Anno, FuncDb} = beam_ssa_type:opt_finish(Args, Anno0, FuncDb0),
+ {St0#st{anno=Anno}, FuncDb}.
+
ssa_opt_blockify({#st{ssa=Linear}=St, FuncDb}) ->
{St#st{ssa=maps:from_list(Linear)}, FuncDb}.