diff options
author | Björn Gustavsson <[email protected]> | 2016-05-13 15:59:31 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2016-05-16 07:51:26 +0200 |
commit | 7f4f4ef02349b4bf973cbc3bacc4d53a6a6abad2 (patch) | |
tree | f1b894393bd7471edf8d486443cbaa98ced0d21e /lib/compiler/src | |
parent | f679efe1c19cb7d6bab8a68226a9d748474ef902 (diff) | |
download | otp-7f4f4ef02349b4bf973cbc3bacc4d53a6a6abad2.tar.gz otp-7f4f4ef02349b4bf973cbc3bacc4d53a6a6abad2.tar.bz2 otp-7f4f4ef02349b4bf973cbc3bacc4d53a6a6abad2.zip |
Eliminate crash in beam_bool
beam_bool would crash when attempting to optimize BEAM code similar
to this code:
bif '=:=' Reg1 SomeValue => y(0)
bif '=:=' Reg2 {atom,true} => x(2)
bif '=:=' Reg3 {atom,true} => x(3)
bif 'or' x(2) x(3) => x(2)
is_eq_exact Fail x(2) {atom,true}
The problem is that the first instruction that assigns a value to a Y
register. beam_bool:ssa_assign/2 will not accept a Y register
argument.
We could change ssa_assign/2 to accept a Y register, but that would
only cause the entire optimization to be rejected later because the Y
register is alive in the code that follows. Therefore, a better
solution is to modify extend_block/3 so that the instruction that
assign to Y registers are not added to the block. That is, the
optimizer will only operate on the following code:
bif '=:=' Reg2 {atom,true} => x(2)
bif '=:=' Reg3 {atom,true} => x(3)
bif 'or' x(2) x(3) => x(2)
is_eq_exact Fail x(2) {atom,true}
Usually the optimization will succeed, rewriting the four instructions
to a select_val instruction.
Assembly code such as the above can be produced by code similar to:
Y = Something == SomethingElse,
case Y of
Condition; OtherCondition ->
. . .
end,
. . .,
Y.
Reported-by: http://bugs.erlang.org/browse/ERL-143
Reported-by: José Valim
Diffstat (limited to 'lib/compiler/src')
-rw-r--r-- | lib/compiler/src/beam_bool.erl | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/lib/compiler/src/beam_bool.erl b/lib/compiler/src/beam_bool.erl index f9a08f8718..359fdb6d3c 100644 --- a/lib/compiler/src/beam_bool.erl +++ b/lib/compiler/src/beam_bool.erl @@ -238,9 +238,9 @@ extend_block(BlAcc0, Fail, [{block,Is0}|OldAcc]) -> end; extend_block(BlAcc, _, OldAcc) -> {BlAcc,OldAcc}. -extend_block_1([{set,[_],_,{bif,_,{f,Fail}}}=I|Is], Fail, Acc) -> +extend_block_1([{set,[{x,_}],_,{bif,_,{f,Fail}}}=I|Is], Fail, Acc) -> extend_block_1(Is, Fail, [I|Acc]); -extend_block_1([{set,[_],As,{bif,Bif,_}}=I|Is]=Is0, Fail, Acc) -> +extend_block_1([{set,[{x,_}],As,{bif,Bif,_}}=I|Is]=Is0, Fail, Acc) -> case safe_bool_op(Bif, length(As)) of false -> {Acc,reverse(Is0)}; true -> extend_block_1(Is, Fail, [I|Acc]) |