diff options
Diffstat (limited to 'lib/compiler/src')
-rw-r--r-- | lib/compiler/src/beam_ssa.erl | 32 | ||||
-rw-r--r-- | lib/compiler/src/beam_ssa_opt.erl | 17 |
2 files changed, 34 insertions, 15 deletions
diff --git a/lib/compiler/src/beam_ssa.erl b/lib/compiler/src/beam_ssa.erl index 2ce00990e0..fc13ba06de 100644 --- a/lib/compiler/src/beam_ssa.erl +++ b/lib/compiler/src/beam_ssa.erl @@ -28,6 +28,7 @@ linearize/1, mapfold_instrs_rpo/4, normalize/1, + no_side_effect/1, predecessors/1, rename_vars/3, rpo/1,rpo/2, @@ -152,6 +153,37 @@ clobbers_xregs(#b_set{op=Op}) -> _ -> false end. +%% no_side_effect(#b_set{}) -> true|false. +%% Test whether this instruction has no side effect and thus is safe +%% not to execute if its value is not used. Note that even if `true` +%% is returned, the instruction could still be impure (e.g. bif:get). + +-spec no_side_effect(b_set()) -> boolean(). + +no_side_effect(#b_set{op=Op}) -> + case Op of + {bif,_} -> true; + {float,get} -> true; + bs_init -> true; + bs_extract -> true; + bs_match -> true; + bs_start_match -> true; + bs_test_tail -> true; + bs_put -> true; + extract -> true; + get_hd -> true; + get_tl -> true; + get_tuple_element -> true; + has_map_field -> true; + is_nonempty_list -> true; + is_tagged_tuple -> true; + put_map -> true; + put_list -> true; + put_tuple -> true; + succeeded -> true; + _ -> false + end. + -spec predecessors(Blocks) -> #{BlockNumber:=[Predecessor]} when Blocks :: block_map(), BlockNumber :: label(), diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl index 257e036719..5f3777072a 100644 --- a/lib/compiler/src/beam_ssa_opt.erl +++ b/lib/compiler/src/beam_ssa_opt.erl @@ -769,14 +769,14 @@ live_opt_is([#b_set{op=succeeded,dst=#b_var{name=SuccDst}=SuccDstVar, end end end; -live_opt_is([#b_set{op=Op,dst=#b_var{name=Dst}}=I|Is], Live0, Acc) -> +live_opt_is([#b_set{dst=#b_var{name=Dst}}=I|Is], Live0, Acc) -> case gb_sets:is_member(Dst, Live0) of true -> Live1 = gb_sets:union(Live0, gb_sets:from_ordset(beam_ssa:used(I))), Live = gb_sets:delete_any(Dst, Live1), live_opt_is(Is, Live, [I|Acc]); false -> - case is_pure(Op) of + case beam_ssa:no_side_effect(I) of true -> live_opt_is(Is, Live0, Acc); false -> @@ -787,19 +787,6 @@ live_opt_is([#b_set{op=Op,dst=#b_var{name=Dst}}=I|Is], Live0, Acc) -> live_opt_is([], Live, Acc) -> {Acc,Live}. -is_pure({bif,_}) -> true; -is_pure({float,get}) -> true; -is_pure(bs_extract) -> true; -is_pure(extract) -> true; -is_pure(get_hd) -> true; -is_pure(get_tl) -> true; -is_pure(get_tuple_element) -> true; -is_pure(is_nonempty_list) -> true; -is_pure(is_tagged_tuple) -> true; -is_pure(put_list) -> true; -is_pure(put_tuple) -> true; -is_pure(_) -> false. - live_opt_unused(#b_set{op=get_map_element}=Set) -> {replace,Set#b_set{op=has_map_field}}; live_opt_unused(_) -> keep. |