diff options
Diffstat (limited to 'lib/compiler')
-rw-r--r-- | lib/compiler/src/beam_utils.erl | 36 | ||||
-rw-r--r-- | lib/compiler/test/compilation_SUITE.erl | 44 |
2 files changed, 65 insertions, 15 deletions
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index 761d4ffec0..45cdf8a659 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -407,16 +407,23 @@ check_liveness(R, [{bif,Op,{f,Fail},Ss,D}|Is], St0) -> Other -> Other end; -check_liveness(R, [{gc_bif,Op,{f,Fail},_,Ss,D}|Is], St0) -> - case check_liveness_fail(R, Op, Ss, Fail, St0) of - {killed,St} = Killed -> - case member(R, Ss) of - true -> {used,St}; - false when R =:= D -> Killed; - false -> check_liveness(R, Is, St) - end; - Other -> - Other +check_liveness(R, [{gc_bif,Op,{f,Fail},Live,Ss,D}|Is], St0) -> + case R of + {x,X} when X >= Live -> + {killed,St0}; + {x,_} -> + {used,St0}; + _ -> + case check_liveness_fail(R, Op, Ss, Fail, St0) of + {killed,St}=Killed -> + case member(R, Ss) of + true -> {used,St}; + false when R =:= D -> Killed; + false -> check_liveness(R, Is, St) + end; + Other -> + Other + end end; check_liveness(R, [{bs_add,{f,0},Ss,D}|Is], St) -> case member(R, Ss) of @@ -482,10 +489,13 @@ check_liveness(R, [{bs_context_to_binary,S}|Is], St) -> S -> {used,St}; _ -> check_liveness(R, Is, St) end; -check_liveness(R, [{loop_rec,{f,_},{x,0}}|Is], St) -> +check_liveness(R, [{loop_rec,{f,_},{x,0}}|_], St) -> case R of - {x,_} -> {killed,St}; - _ -> check_liveness(R, Is, St) + {x,_} -> + {killed,St}; + _ -> + %% y register. Rarely happens. Be very conversative. + {unknown,St} end; check_liveness(R, [{loop_rec_end,{f,Fail}}|_], St) -> check_liveness_at(R, Fail, St); diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl index 9c06740816..935e384d2d 100644 --- a/lib/compiler/test/compilation_SUITE.erl +++ b/lib/compiler/test/compilation_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2010. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -46,7 +46,7 @@ all(suite) -> trycatch_4, opt_crash, otp_5404,otp_5436,otp_5481,otp_5553,otp_5632, otp_5714,otp_5872,otp_6121,otp_6121a,otp_6121b, - otp_7202,otp_7345,on_load,string_table + otp_7202,otp_7345,on_load,string_table,otp_8949_a,otp_8949_a ]. -define(comp(N), @@ -606,5 +606,45 @@ string_table(Config) when is_list(Config) -> ?line {"StrT", <<"stringabletringtable">>} = StringTableChunk, ok. +otp_8949_a(Config) when is_list(Config) -> + value = otp_8949_a(), + ok. + +-record(cs, {exs,keys = [],flags = 1}). +-record(exs, {children = []}). + +otp_8949_a() -> + case id([#cs{}]) of + [#cs{}=Cs] -> + SomeVar = id(value), + if + Cs#cs.flags band 1 =/= 0 -> + id(SomeVar); + (((Cs#cs.exs)#exs.children /= []) + and + (Cs#cs.flags band (1 bsl 0 bor (1 bsl 22)) == 0)); + Cs#cs.flags band (1 bsl 22) =/= 0 -> + ok + end + end. + +otp_8949_b(Config) when is_list(Config) -> + self() ! something, + ?line value = otp_8949_b([], false), + ?line {'EXIT',_} = (catch otp_8949_b([], true)), + ok. + +%% Would cause an endless loop in beam_utils. +otp_8949_b(A, B) -> + Var = id(value), + if + A == [], B == false -> + ok + end, + receive + something -> + id(Var) + end. + id(I) -> I. |