diff options
author | Björn Gustavsson <[email protected]> | 2019-01-30 07:20:33 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2019-02-01 12:44:32 +0100 |
commit | 855af19300720a8d0dbb588a4c145ad5ffe1453e (patch) | |
tree | 5296ea6ada2ba58ad6f2fc81d27a8ca7c48108eb /lib/compiler/src/beam_ssa_type.erl | |
parent | 7306c730fa3ce28ec47c31ab307e0d3d0105677a (diff) | |
download | otp-855af19300720a8d0dbb588a4c145ad5ffe1453e.tar.gz otp-855af19300720a8d0dbb588a4c145ad5ffe1453e.tar.bz2 otp-855af19300720a8d0dbb588a4c145ad5ffe1453e.zip |
beam_ssa_type: Optimize calculation of variables that are only used once
Diffstat (limited to 'lib/compiler/src/beam_ssa_type.erl')
-rw-r--r-- | lib/compiler/src/beam_ssa_type.erl | 53 |
1 files changed, 30 insertions, 23 deletions
diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl index 8bd6772ac5..32583f5abf 100644 --- a/lib/compiler/src/beam_ssa_type.erl +++ b/lib/compiler/src/beam_ssa_type.erl @@ -1081,44 +1081,51 @@ simplify_not(#b_br{bool=#b_var{}=V,succ=Succ,fail=Fail}=Br0, Ts, Ds) -> used_once(Linear, Args) -> Map0 = used_once_1(reverse(Linear), #{}), Map = maps:without(Args, Map0), - Used0 = cerl_sets:from_list(maps:keys(Map)), - Used1 = used_in_terminators(Linear, []), - cerl_sets:intersection(Used0, Used1). - -used_in_terminators([{_,#b_blk{last=Last}}|Bs], Acc) -> - used_in_terminators(Bs, beam_ssa:used(Last) ++ Acc); -used_in_terminators([], Acc) -> - cerl_sets:from_list(Acc). + cerl_sets:from_list(maps:keys(Map)). used_once_1([{L,#b_blk{is=Is,last=Last}}|Bs], Uses0) -> - Uses = used_once_2([Last|reverse(Is)], L, Uses0), + Uses1 = used_once_last_uses(beam_ssa:used(Last), L, Uses0), + Uses = used_once_2(reverse(Is), L, Uses1), used_once_1(Bs, Uses); used_once_1([], Uses) -> Uses. -used_once_2([I|Is], L, Uses0) -> +used_once_2([#b_set{dst=Dst}=I|Is], L, Uses0) -> Uses = used_once_uses(beam_ssa:used(I), L, Uses0), - case I of - #b_set{dst=Dst} -> - case Uses of - #{Dst:=[L]} -> - used_once_2(Is, L, Uses); - #{} -> - used_once_2(Is, L, maps:remove(Dst, Uses)) - end; - _ -> - used_once_2(Is, L, Uses) + case Uses of + #{Dst:=[L]} -> + used_once_2(Is, L, Uses); + #{} -> + %% Used more than once or used once in + %% in another block. + used_once_2(Is, L, maps:remove(Dst, Uses)) end; used_once_2([], _, Uses) -> Uses. used_once_uses([V|Vs], L, Uses) -> case Uses of - #{V:=Us} -> - used_once_uses(Vs, L, Uses#{V:=[L|Us]}); + #{V:=more_than_once} -> + used_once_uses(Vs, L, Uses); #{} -> - used_once_uses(Vs, L, Uses#{V=>[L]}) + %% Already used or first use is not in + %% a terminator. + used_once_uses(Vs, L, Uses#{V=>more_than_once}) end; used_once_uses([], _, Uses) -> Uses. +used_once_last_uses([V|Vs], L, Uses) -> + case Uses of + #{V:=[_]} -> + %% Second time this variable is used. + used_once_last_uses(Vs, L, Uses#{V:=more_than_once}); + #{V:=more_than_once} -> + %% Used at least twice before. + used_once_last_uses(Vs, L, Uses); + #{} -> + %% First time this variable is used. + used_once_last_uses(Vs, L, Uses#{V=>[L]}) + end; +used_once_last_uses([], _, Uses) -> Uses. + get_types(Values, Ts) -> [get_type(Val, Ts) || Val <- Values]. |