diff options
Diffstat (limited to 'lib/compiler/src/beam_ssa_recv.erl')
-rw-r--r-- | lib/compiler/src/beam_ssa_recv.erl | 52 |
1 files changed, 34 insertions, 18 deletions
diff --git a/lib/compiler/src/beam_ssa_recv.erl b/lib/compiler/src/beam_ssa_recv.erl index 9d6e749fb7..f1d58ffb16 100644 --- a/lib/compiler/src/beam_ssa_recv.erl +++ b/lib/compiler/src/beam_ssa_recv.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2018-2021. All Rights Reserved. +%% Copyright Ericsson AB 2018-2022. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -217,25 +217,37 @@ scan_is([#b_set{op=new_try_tag,dst=Dst}], Blk, Lbl, _Blocks, FuncId, State) -> %% ignore that branch. #b_br{bool=Dst,succ=Succ} = Blk#b_blk.last, %Assertion. scan_add_edge({FuncId, Lbl}, {FuncId, Succ}, State); -scan_is([#b_set{op=call,dst=Dst,args=[#b_remote{} | _]}=Call | Is], - Blk, Lbl, Blocks, FuncId, State0) -> - case {Is, Blk#b_blk.last} of - {[], #b_ret{arg=Dst}} -> - scan_is(Is, Blk, Lbl, Blocks, FuncId, State0); - {[#b_set{op={succeeded,body}}], #b_br{bool=Bool,succ=Succ}} -> - #b_var{} = Bool, %Assertion. +scan_is([#b_set{op=call,dst=Dst,args=[#b_remote{} | _]}=Call, + #b_set{op={succeeded,body}}], + #b_blk{last=#b_br{succ=Succ}}, Lbl, Blocks, FuncId, State0) -> + case Blocks of + #{ Succ := #b_blk{is=[],last=#b_ret{arg=Dst}}} -> + %% External tail call, ignore it altogether. + State0; + #{} -> State = si_remote_call(Call, Lbl, Succ, Blocks, FuncId, State0), - scan_is(Is, Blk, Lbl, Blocks, FuncId, State); - _ -> - State = si_remote_call(Call, Lbl, Lbl, Blocks, FuncId, State0), - scan_is(Is, Blk, Lbl, Blocks, FuncId, State) + scan_add_edge({FuncId, Lbl}, {FuncId, Succ}, State) + end; +scan_is([#b_set{op=call,args=[#b_remote{} | _]}=Call | Is], + Blk, Lbl, Blocks, FuncId, State0) -> + %% Remote call that always succeeds. + State = si_remote_call(Call, Lbl, Lbl, Blocks, FuncId, State0), + scan_is(Is, Blk, Lbl, Blocks, FuncId, State); +scan_is([#b_set{op=call,dst=Dst,args=[#b_local{}=Callee | Args]}, + #b_set{op={succeeded,body},args=[Dst]}], + #b_blk{last=#b_br{succ=Succ}}, + Lbl, Blocks, FuncId, State0) -> + case Blocks of + #{ Succ := #b_blk{is=[],last=#b_ret{arg=Dst}}} -> + %% Local tail call, don't add any edges. + scan_add_call(tail, Args, Callee, Lbl, FuncId, State0); + #{} -> + State = scan_add_call(body, Args, Callee, Lbl, FuncId, State0), + scan_add_edge({FuncId, Lbl}, {FuncId, Succ}, State) end; -scan_is([#b_set{op=call,dst=Dst,args=[#b_local{}=Callee | Args]}], - #b_blk{last=#b_ret{arg=Dst}}, Lbl, _Blocks, FuncId, State) -> - scan_add_call(tail, Args, Callee, Lbl, FuncId, State); -scan_is([#b_set{op=call,dst=Dst,args=[#b_local{}=Callee | Args]} | Is], +scan_is([#b_set{op=call,args=[#b_local{}=Callee | Args]} | Is], Blk, Lbl, Blocks, FuncId, State0) -> - [#b_set{op={succeeded,body},args=[Dst]}] = Is, %Assertion. + %% Local call that always succeeds. State = scan_add_call(body, Args, Callee, Lbl, FuncId, State0), scan_is(Is, Blk, Lbl, Blocks, FuncId, State); scan_is([_I | Is], Blk, Lbl, Blocks, FuncId, State) -> @@ -894,7 +906,11 @@ coi_creations([], _Blocks, _Defs) -> []. make_warning(Term, Anno, Where) -> - {File, Line} = maps:get(location, Anno, Where), + {File, Line} = + case maps:get(location, Anno, Where) of + {_, _} = Location -> Location; + _ -> {"no_file", none} + end, {File,[{Line,?MODULE,Term}]}. format_opt_info(matches_any_message) -> |