From c30b5cb6ada1fd119356f54c90a2f660d5f08c1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 6 Apr 2011 10:51:45 +0200 Subject: beam_dead: Remove code that cannot be covered in forward/4 Since the optimizations in forward/4 already depends on some assumptions on how code is generated anyway, document the assumptions in a comment and remove the uncoverable code. --- lib/compiler/src/beam_dead.erl | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) (limited to 'lib/compiler/src') diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl index bb93110176..135c7757c5 100644 --- a/lib/compiler/src/beam_dead.erl +++ b/lib/compiler/src/beam_dead.erl @@ -246,30 +246,24 @@ forward([{select_val,Reg,_,{list,List}}=I|Is], D0, Lc, Acc) -> D = update_value_dict(List, Reg, D0), forward(Is, D, Lc, [I|Acc]); forward([{label,Lbl}=LblI,{block,[{set,[Dst],[Lit],move}|BlkIs]}=Blk|Is], D, Lc, Acc) -> + %% Assumption: The target labels in a select_val/3 instruction + %% cannot be reached in any other way than through the select_val/3 + %% instruction (i.e. there can be no fallthrough to such label and + %% it cannot be referenced by, for example, a jump/1 instruction). Block = case gb_trees:lookup({Lbl,Dst}, D) of - {value,Lit} -> - %% The move instruction seems to be redundant, but also make - %% sure that the instruction preceeding the label - %% cannot fall through to the move instruction. - case is_unreachable_after(Acc) of - false -> Blk; %Must keep move instruction. - true -> {block,BlkIs} %Safe to remove move instruction. - end; - _ -> Blk %Keep move instruction. + {value,Lit} -> {block,BlkIs}; %Safe to remove move instruction. + _ -> Blk %Must keep move instruction. end, forward([Block|Is], D, Lc, [LblI|Acc]); forward([{label,Lbl}=LblI|[{move,Lit,Dst}|Is1]=Is0], D, Lc, Acc) -> + %% Assumption: The target labels in a select_val/3 instruction + %% cannot be reached in any other way than through the select_val/3 + %% instruction (i.e. there can be no fallthrough to such label and + %% it cannot be referenced by, for example, a jump/1 instruction). Is = case gb_trees:lookup({Lbl,Dst}, D) of - {value,Lit} -> - %% The move instruction seems to be redundant, but also make - %% sure that the instruction preceeding the label - %% cannot fall through to the move instruction. - case is_unreachable_after(Acc) of - false -> Is0; %Must keep move instruction. - true -> Is1 %Safe to remove move instruction. - end; - _ -> Is0 %Keep move instruction. - end, + {value,Lit} -> Is1; %Safe to remove move instruction. + _ -> Is0 %Keep move instruction. + end, forward(Is, D, Lc, [LblI|Acc]); forward([{test,is_eq_exact,_,[Dst,Src]}=I, {block,[{set,[Dst],[Src],move}|Bl]}|Is], D, Lc, Acc) -> @@ -306,9 +300,6 @@ update_value_dict([Lit,{f,Lbl}|T], Reg, D0) -> update_value_dict(T, Reg, D); update_value_dict([], _, D) -> D. -is_unreachable_after([I|_]) -> - beam_jump:is_unreachable_after(I). - %%% %%% Scan instructions in reverse execution order and remove dead code. %%% -- cgit v1.2.3 From ce34176deaffd219e921cb70f271bbc693061fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 6 Apr 2011 10:57:15 +0200 Subject: beam_dead: Remove uncoverable case clause in update_value_dict/3 Because the code generator (v3_codegen) would not include the same value more than once in a select_val/3 instruction and because a label can only be referenced by one select_val/3 instruction, there is no way that the correct value could already be in the gb_tree. (Even if it could happen, this change is safe because only opportunity for an optimization would be missed; incorrect code would not be generated.) --- lib/compiler/src/beam_dead.erl | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/compiler/src') diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl index 135c7757c5..0afb027d3a 100644 --- a/lib/compiler/src/beam_dead.erl +++ b/lib/compiler/src/beam_dead.erl @@ -293,7 +293,6 @@ update_value_dict([Lit,{f,Lbl}|T], Reg, D0) -> Key = {Lbl,Reg}, D = case gb_trees:lookup(Key, D0) of none -> gb_trees:insert(Key, Lit, D0); %New. - {value,Lit} -> D0; %Already correct. {value,inconsistent} -> D0; %Inconsistent. {value,_} -> gb_trees:update(Key, inconsistent, D0) end, -- cgit v1.2.3 From 981acf6eaa48adffb27b2e812db8bcd180121f4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 11 Apr 2011 12:15:09 +0200 Subject: beam_dead: Remove uncovered clauses in binary matching optimization In the optimization of binary matching, it seems that two clauses cannot never be reached. Removing the clauses is safe, since that would only mean that an opportunity for an optimization is lost --- lib/compiler/src/beam_dead.erl | 5 ----- 1 file changed, 5 deletions(-) (limited to 'lib/compiler/src') diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl index 0afb027d3a..73f45452fa 100644 --- a/lib/compiler/src/beam_dead.erl +++ b/lib/compiler/src/beam_dead.erl @@ -592,16 +592,11 @@ count_bits_matched([{test,_,_,_}|Is], SavePoint, Bits) -> count_bits_matched([{bs_save2,Reg,SavePoint}|_], {Reg,SavePoint}, Bits) -> %% The save point we are looking for - we are done. Bits; -count_bits_matched([{bs_save2,_,_}|Is], SavePoint, Bits) -> - %% Another save point - keep counting. - count_bits_matched(Is, SavePoint, Bits); count_bits_matched([_|_], _, Bits) -> Bits. shortcut_bs_pos_used(To, Reg, D) -> shortcut_bs_pos_used_1(beam_utils:code_at(To, D), Reg, D). -shortcut_bs_pos_used_1([{bs_restore2,Reg,_}|_], Reg, _) -> - false; shortcut_bs_pos_used_1([{bs_context_to_binary,Reg}|_], Reg, _) -> false; shortcut_bs_pos_used_1(Is, Reg, D) -> -- cgit v1.2.3 From df96e44eb23abdb696eb79ecc92ce4f8bbb534a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 12 Apr 2011 05:44:27 +0200 Subject: beam_dead: Remove uncovered special case handling of empty blocks There is never any empty blocks when beam_dead is invoked. Even if there were, they will be removed a little bit later in forward/4. --- lib/compiler/src/beam_dead.erl | 3 --- 1 file changed, 3 deletions(-) (limited to 'lib/compiler/src') diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl index 73f45452fa..8e96569414 100644 --- a/lib/compiler/src/beam_dead.erl +++ b/lib/compiler/src/beam_dead.erl @@ -162,14 +162,11 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) -> %% We must split the basic block when we encounter instructions with labels, %% such as catches and BIFs. All labels must be visible outside the blocks. -%% Also remove empty blocks. split_blocks({function,Name,Arity,CLabel,Is0}) -> Is = split_blocks(Is0, []), {function,Name,Arity,CLabel,Is}. -split_blocks([{block,[]}|Is], Acc) -> - split_blocks(Is, Acc); split_blocks([{block,Bl}|Is], Acc0) -> Acc = split_block(Bl, [], Acc0), split_blocks(Is, Acc); -- cgit v1.2.3 From 13be8d88969caa266b07d09294094a4cce8bbd8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Sun, 10 Apr 2011 11:10:56 +0200 Subject: beam_bsm: Eliminate uncovered line in warning generation In warning_translate_label/2, gb_trees:lookup/2 is called to translate from the entry label for a function to its name. Since the gb_tree has an entry for all functions in the module, there is no way that the lookup can fail unless there is a serious bug. Therefore, use gb_trees:get/2 so that an exception and an internal compiler error will be generated if the lookup would ever fail. --- lib/compiler/src/beam_bsm.erl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'lib/compiler/src') diff --git a/lib/compiler/src/beam_bsm.erl b/lib/compiler/src/beam_bsm.erl index 2a36fda1ea..5cc8252b99 100644 --- a/lib/compiler/src/beam_bsm.erl +++ b/lib/compiler/src/beam_bsm.erl @@ -651,10 +651,8 @@ add_warning(Term, Anno, Ws) -> warning_translate_label(Term, D) when is_tuple(Term) -> case element(1, Term) of {label,F} -> - case gb_trees:lookup(F, D) of - none -> Term; - {value,FA} -> setelement(1, Term, FA) - end; + FA = gb_trees:get(F, D), + setelement(1, Term, FA); _ -> Term end; warning_translate_label(Term, _) -> Term. -- cgit v1.2.3