diff options
| author | Björn Gustavsson <[email protected]> | 2016-04-07 12:43:06 +0200 | 
|---|---|---|
| committer | Björn Gustavsson <[email protected]> | 2016-04-08 10:28:42 +0200 | 
| commit | ab03678e87732407625150c202e177a85a025beb (patch) | |
| tree | 881f543c0f7ca0cb099fe3eec71a7b37b0bf27be | |
| parent | 3c0f98c1b0e74eb58a4e4e82a3ec89dc7ecdb579 (diff) | |
| download | otp-ab03678e87732407625150c202e177a85a025beb.tar.gz otp-ab03678e87732407625150c202e177a85a025beb.tar.bz2 otp-ab03678e87732407625150c202e177a85a025beb.zip | |
Remove unreachable code after 'raise' instructions
Remove the unreachable instructions after a 'raise' instruction
(e.g. a 'jump' or 'deallocate', 'return') to decrease code size.
| -rw-r--r-- | lib/compiler/src/beam_block.erl | 4 | ||||
| -rw-r--r-- | lib/compiler/src/beam_split.erl | 2 | ||||
| -rw-r--r-- | lib/compiler/src/beam_validator.erl | 3 | ||||
| -rw-r--r-- | lib/compiler/src/beam_z.erl | 12 | ||||
| -rw-r--r-- | lib/compiler/test/beam_validator_SUITE.erl | 2 | 
5 files changed, 21 insertions, 2 deletions
| diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index d1052303e0..429b1aa010 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -88,7 +88,9 @@ collect_block([I|Is]=Is0, Acc) ->      case collect(I) of  	error -> {reverse(Acc),Is0};  	Instr -> collect_block(Is, [Instr|Acc]) -    end. +    end; +collect_block([], Acc) -> +    {reverse(Acc),[]}.  collect({allocate,N,R})      -> {set,[],[],{alloc,R,{nozero,N,0,[]}}};  collect({allocate_zero,N,R}) -> {set,[],[],{alloc,R,{zero,N,0,[]}}}; diff --git a/lib/compiler/src/beam_split.erl b/lib/compiler/src/beam_split.erl index bb1c0e23a9..7b7f0a0f80 100644 --- a/lib/compiler/src/beam_split.erl +++ b/lib/compiler/src/beam_split.erl @@ -47,6 +47,8 @@ split_block([{set,[R],[_,_,_]=As,{bif,is_record,{f,Lbl}}}|Is], Bl, Acc) ->      split_block(Is, [], [{bif,is_record,{f,Lbl},As,R}|make_block(Bl, Acc)]);  split_block([{set,[R],As,{bif,N,{f,Lbl}=Fail}}|Is], Bl, Acc) when Lbl =/= 0 ->      split_block(Is, [], [{bif,N,Fail,As,R}|make_block(Bl, Acc)]); +split_block([{set,[R],As,{bif,raise,{f,_}=Fail}}|Is], Bl, Acc) -> +    split_block(Is, [], [{bif,raise,Fail,As,R}|make_block(Bl, Acc)]);  split_block([{set,[R],As,{alloc,Live,{gc_bif,N,{f,Lbl}=Fail}}}|Is], Bl, Acc)    when Lbl =/= 0 ->      split_block(Is, [], [{gc_bif,N,Fail,Live,As,R}|make_block(Bl, Acc)]); diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index fd38fc0095..1c052789fd 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -509,6 +509,9 @@ valfun_4({bif,element,{f,Fail},[Pos,Tuple],Dst}, Vst0) ->      TupleType = upgrade_tuple_type({tuple,[get_tuple_size(PosType)]}, TupleType0),      Vst = set_type(TupleType, Tuple, Vst1),      set_type_reg(term, Dst, Vst); +valfun_4({bif,raise,{f,0},Src,_Dst}, Vst) -> +    validate_src(Src, Vst), +    kill_state(Vst);  valfun_4({bif,Op,{f,Fail},Src,Dst}, Vst0) ->      validate_src(Src, Vst0),      Vst = branch_state(Fail, Vst0), diff --git a/lib/compiler/src/beam_z.erl b/lib/compiler/src/beam_z.erl index 8381578b68..e44423d257 100644 --- a/lib/compiler/src/beam_z.erl +++ b/lib/compiler/src/beam_z.erl @@ -24,6 +24,8 @@  -export([module/2]). +-import(lists, [dropwhile/2]). +  module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->      Fs = [function(F) || F <- Fs0],      {ok,{Mod,Exp,Attr,Fs,Lc}}. @@ -51,6 +53,16 @@ undo_renames([{call,A,F},return|Is]) ->      [{call_only,A,F}|undo_renames(Is)];  undo_renames([{call_ext,A,F},return|Is]) ->      [{call_ext_only,A,F}|undo_renames(Is)]; +undo_renames([{bif,raise,_,_,_}=I|Is0]) -> +    %% A minor optimization. Done here because: +    %%  (1) beam_jump may move or share 'raise' instructions, and that +    %%      may confuse beam_validator. +    %%  (2) beam_trim cannot do its optimization if the 'deallocate' +    %%      instruction after 'raise' has been removed. +    Is = dropwhile(fun({label,_}) -> false; +		      (_) -> true +		   end, Is0), +    [I|undo_renames(Is)];  undo_renames([I|Is]) ->      [undo_rename(I)|undo_renames(Is)];  undo_renames([]) -> []. diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl index d27512b6eb..b3fb091f46 100644 --- a/lib/compiler/test/beam_validator_SUITE.erl +++ b/lib/compiler/test/beam_validator_SUITE.erl @@ -312,7 +312,7 @@ state_after_fault_in_catch(Config) when is_list(Config) ->  no_exception_in_catch(Config) when is_list(Config) ->      Errors = do_val(no_exception_in_catch, Config),      [{{no_exception_in_catch,nested_of_1,4}, -      {{move,{x,3},{x,0}},88,{uninitialized_reg,{x,3}}}}] = Errors, +      {{move,{x,3},{x,0}},87,{uninitialized_reg,{x,3}}}}] = Errors,      ok.  undef_label(Config) when is_list(Config) -> | 
