Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:25
erlang
0138-Eliminate-crash-when-optimization-passes-a...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0138-Eliminate-crash-when-optimization-passes-are-disable.patch of Package erlang
From c723601d49df30e6ffa7a2d8a40cdef973b67759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org> Date: Tue, 14 Jun 2022 05:30:23 +0200 Subject: [PATCH] Eliminate crash when optimization passes are disabled When compiling the following code with optimization passes disabled: foo() -> ([<<bad/utf8>>] = try [whatever] catch _:_ when false -> ok end) ! (some_atom ++ <<>>). `beam_validator` rejects the code with the following message: some_module:1: function foo/0+11: Internal consistency check failed - please report this bug. Instruction: {get_hd,{literal,[whatever]},{x,0}} Error: {literal_not_allowed,{literal,[whatever]}}: All optimization passes are supposed to be optional, so this crash is not acceptable even though the code is nonsensical. Eliminate the crash by having `beam_ssa_pre_codegen` re-run its code cleaning pass until there are no more unreachable blocks. --- lib/compiler/src/beam_ssa_pre_codegen.erl | 78 ++++++++++++----------- lib/compiler/test/beam_ssa_SUITE.erl | 14 ++++ 2 files changed, 55 insertions(+), 37 deletions(-) diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl index 0c7ee89bf0..c5b428759c 100644 --- a/lib/compiler/src/beam_ssa_pre_codegen.erl +++ b/lib/compiler/src/beam_ssa_pre_codegen.erl @@ -74,7 +74,7 @@ -import(lists, [all/2,any/2,append/1,duplicate/2, foldl/3,last/1,member/2,partition/2, reverse/1,reverse/2,seq/2,sort/1, - splitwith/2,usort/1,zip/2]). + usort/1,zip/2]). -spec module(beam_ssa:b_module(), [compile:option()]) -> {'ok',beam_ssa:b_module()}. @@ -588,10 +588,13 @@ bs_subst_ctx(Other, _CtxChain) -> %% arguments. Evaluate the instructions and remove them. sanitize(#st{ssa=Blocks0,cnt=Count0}=St) -> - Ls = beam_ssa:rpo(Blocks0), - {Blocks,Count} = sanitize(Ls, Blocks0, Count0, #{}), + {Blocks,Count} = sanitize(Blocks0, Count0), St#st{ssa=Blocks,cnt=Count}. +sanitize(Blocks, Counts) -> + Ls = beam_ssa:rpo(Blocks), + sanitize(Ls, Blocks, Counts, #{}). + sanitize([L|Ls], Blocks0, Count0, Values0) -> #b_blk{is=Is0,last=Last0} = Blk0 = map_get(L, Blocks0), case sanitize_is(Is0, Last0, Blocks0, Count0, Values0, false, []) of @@ -603,21 +606,28 @@ sanitize([L|Ls], Blocks0, Count0, Values0) -> sanitize(Ls, Blocks, Count, Values) end; sanitize([], Blocks0, Count, Values) -> - Blocks = if - map_size(Values) =:= 0 -> - Blocks0; - true -> - RPO = beam_ssa:rpo(Blocks0), - beam_ssa:rename_vars(Values, RPO, Blocks0) - end, + Blocks1 = if + map_size(Values) =:= 0 -> + Blocks0; + true -> + RPO = beam_ssa:rpo(Blocks0), + beam_ssa:rename_vars(Values, RPO, Blocks0) + end, %% Unreachable blocks can cause problems for the dominator calculations. - Ls = beam_ssa:rpo(Blocks), - Reachable = gb_sets:from_list(Ls), - {case map_size(Blocks) =:= gb_sets:size(Reachable) of - true -> Blocks; - false -> remove_unreachable(Ls, Blocks, Reachable, []) - end, Count}. + Linear = beam_ssa:linearize(Blocks1), + if + map_size(Blocks1) =:= length(Linear) -> + {Blocks1,Count}; + true -> + %% Since blocks were removed, some phi nodes could have + %% been reduced to a single value. Single-valued phi nodes + %% can cause problem when beam_ssa_codegen does its own + %% constant propagation, so we will have re-run this pass + %% to get rid of any single-valued phi nodes. + Blocks = maps:from_list(Linear), + sanitize(Blocks, Count) + end. sanitize_is([#b_set{op=get_map_element,args=Args0}=I0|Is], Last, Blocks, Count0, Values, Changed, Acc) -> @@ -702,6 +712,19 @@ sanitize_is([#b_set{op=bs_test_tail}=I], Last, Blocks, Count, Values, _ -> do_sanitize_is(I, [], Last, Blocks, Count, Values, Changed, Acc) end; +sanitize_is([#b_set{op=bs_get,args=Args0}=I0|Is], Last, Blocks, Count, Values, + Changed, Acc) -> + case {Args0,sanitize_args(Args0, Values)} of + {[_,_,_,#b_var{},_],[Type,Val,Flags,#b_literal{val=all},Unit]} -> + %% The size `all` is used for the size of the final binary + %% segment in a pattern. Using `all` explicitly is not allowed, + %% so we convert it to an obvious invalid size. + Args = [Type,Val,Flags,#b_literal{val=bad_size},Unit], + I = I0#b_set{args=Args}, + sanitize_is(Is, Last, Blocks, Count, Values, true, [I|Acc]); + {_,_} -> + sanitize_is(Is, Last, Blocks, Count, Values, Changed, [I0|Acc]) + end; sanitize_is([#b_set{}=I|Is], Last, Blocks, Count, Values, Changed, Acc) -> do_sanitize_is(I, Is, Last, Blocks, Count, Values, Changed, Acc); sanitize_is([], Last, _Blocks, Count, Values, Changed, Acc) -> @@ -807,27 +830,11 @@ sanitize_instr(is_tagged_tuple, [#b_literal{val=Tuple}, true -> {value,false} end; +sanitize_instr(succeeded, [#b_literal{}], _I) -> + {value,true}; sanitize_instr(_, _, _) -> ok. -remove_unreachable([L|Ls], Blocks, Reachable, Acc) -> - #b_blk{is=Is0} = Blk0 = map_get(L, Blocks), - case split_phis(Is0) of - {[_|_]=Phis,Rest} -> - Is = [prune_phi(Phi, Reachable) || Phi <- Phis] ++ Rest, - Blk = Blk0#b_blk{is=Is}, - remove_unreachable(Ls, Blocks, Reachable, [{L,Blk}|Acc]); - {[],_} -> - remove_unreachable(Ls, Blocks, Reachable, [{L,Blk0}|Acc]) - end; -remove_unreachable([], _Blocks, _, Acc) -> - maps:from_list(Acc). - -prune_phi(#b_set{args=Args0}=Phi, Reachable) -> - Args = [A || {_,Pred}=A <- Args0, - gb_sets:is_element(Pred, Reachable)], - Phi#b_set{args=Args}. - phi_all_same_literal([{#b_literal{}=Arg, _From} | Phis]) -> phi_all_same_literal_1(Phis, Arg); phi_all_same_literal([_|_]) -> @@ -3048,9 +3055,6 @@ rel2fam(S0) -> S = sofs:rel2fam(S1), sofs:to_external(S). -split_phis(Is) -> - splitwith(fun(#b_set{op=Op}) -> Op =:= phi end, Is). - is_yreg({y,_}) -> true; is_yreg({x,_}) -> false; is_yreg({z,_}) -> false; diff --git a/lib/compiler/test/beam_ssa_SUITE.erl b/lib/compiler/test/beam_ssa_SUITE.erl index d1330b78bf..21715fd15c 100644 --- a/lib/compiler/test/beam_ssa_SUITE.erl +++ b/lib/compiler/test/beam_ssa_SUITE.erl @@ -886,6 +886,8 @@ grab_bag(_Config) -> {'EXIT',{{try_clause,[]},[_|_]}} = catch grab_bag_18(), + {'EXIT',{{badmatch,[whatever]},[_|_]}} = catch grab_bag_19(), + ok. grab_bag_1() -> @@ -1112,6 +1114,18 @@ grab_bag_18() -> end end. +grab_bag_19() -> + ([<<bad/utf8>>] = + %% beam_ssa_pre_codegen would produce single-valued phi + %% nodes, which in turn would cause the constant propagation + %% in beam_ssa_codegen:prefer_xregs/2 to produce get_hd and + %% get_tl instructions with literal operands. + try + [whatever] + catch + _:_ when false -> + ok + end) ! (some_atom ++ <<>>). redundant_br(_Config) -> {false,{x,y,z}} = redundant_br_1(id({x,y,z})), -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor