diff options
author | Björn Gustavsson <[email protected]> | 2018-08-21 08:58:15 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2018-09-17 06:41:02 +0200 |
commit | 70bb14fe3fd27e8c429bf402e364b144a5807d9a (patch) | |
tree | c8c86337d5324e900ce483eb49b32227a3a314d2 /lib/compiler/src/beam_ssa_opt.erl | |
parent | ec1f35c9f52be894ba295b9a48237020855e3c46 (diff) | |
download | otp-70bb14fe3fd27e8c429bf402e364b144a5807d9a.tar.gz otp-70bb14fe3fd27e8c429bf402e364b144a5807d9a.tar.bz2 otp-70bb14fe3fd27e8c429bf402e364b144a5807d9a.zip |
Add beam_ssa_dead.erl
Add beam_ssa_dead to perform the main optimizations done
by beam_dead:
* Shortcut branches that jump to another block with a branch.
If it can be seen that the second branch will always branch
to a specific block, replace the target of the first branch.
* Combined nested sequences of '=:=' tests and switch
instructions operating on the same variable to a single switch.
Diffing the compiler output, it seems that beam_ssa_dead finds
many more opportunities for optimizations than beam_dead,
although it does not find all opportunities that beam_dead does.
In total, beam_ssa_dead is such improvement over beam_dead that
there is no reason to keep beam_dead as well as beam_ssa_dead.
Note that beam_ssa_dead does not attempt to optimize away
redundant bs_context_binary instructions, because that instruction
will be superseded by new instructions in the near future.
Diffstat (limited to 'lib/compiler/src/beam_ssa_opt.erl')
-rw-r--r-- | lib/compiler/src/beam_ssa_opt.erl | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl index 2174c6aa31..83ee918b25 100644 --- a/lib/compiler/src/beam_ssa_opt.erl +++ b/lib/compiler/src/beam_ssa_opt.erl @@ -52,10 +52,19 @@ passes(Opts0) -> ?PASS(ssa_opt_element), ?PASS(ssa_opt_linearize), ?PASS(ssa_opt_record), + + %% Run ssa_opt_cse twice, because it will help ssa_opt_dead, + %% and ssa_opt_dead will help ssa_opt_cse. Run ssa_opt_live + %% twice, because it will help ssa_opt_dead and ssa_opt_dead + %% will help ssa_opt_live. ?PASS(ssa_opt_cse), ?PASS(ssa_opt_type), - ?PASS(ssa_opt_float), ?PASS(ssa_opt_live), + ?PASS(ssa_opt_dead), + ?PASS(ssa_opt_cse), %Second time. + ?PASS(ssa_opt_float), + ?PASS(ssa_opt_live), %Second time. + ?PASS(ssa_opt_bsm), ?PASS(ssa_opt_bsm_shortcut), ?PASS(ssa_opt_misc), @@ -91,6 +100,9 @@ function(#b_function{anno=Anno,bs=Blocks0,args=Args,cnt=Count0}=F, Ps) -> %%% Trivial sub passes. %%% +ssa_opt_dead(#st{ssa=Linear}=St) -> + St#st{ssa=beam_ssa_dead:opt(Linear)}. + ssa_opt_linearize(#st{ssa=Blocks}=St) -> St#st{ssa=beam_ssa:linearize(Blocks)}. @@ -493,11 +505,13 @@ cse_suitable(#b_set{op={bif,tuple_size}}) -> %% and beam_validator could fail to understand %% that tuple operations that follow are safe. false; -cse_suitable(#b_set{op={bif,Name},args=Args}) -> +cse_suitable(#b_set{anno=Anno,op={bif,Name},args=Args}) -> + %% Doing CSE for floating point operators is unsafe. %% Doing CSE for comparison operators would prevent %% creation of 'test' instructions. Arity = length(Args), - not (erl_internal:new_type_test(Name, Arity) orelse + not (is_map_key(float_op, Anno) orelse + erl_internal:new_type_test(Name, Arity) orelse erl_internal:comp_op(Name, Arity) orelse erl_internal:bool_op(Name, Arity)); cse_suitable(#b_set{}) -> false. |