|
The following code (by Simon Cornish)
bad(XDo1, XDo2, Do3) ->
Do1 = (XDo1 =/= []),
Do2 = (XDo2 =/= []),
CH1 = if Do1 == true;
Do1 == false,Do2==false,Do3 == blah ->
ch1;
true ->
no
end,
CH2 = if Do1 == true;
Do1 == false,Do2==false,Do3 == xx ->
ch2;
true ->
no
end,
{CH1,CH2}.
is optimized by beam_bool even though the optimization is not
safe. The trouble is that an assignment to {y,0} no longer
occurs on all paths leading to its use.
The bug is in dst_regs/2 which is supposed to return a set
of all registers assigned in a code block, but it ignores
registers assigned in 'move' instructions.
Fix the bug by taking 'move' instructions into account. This change
is safe since it can only cause more registers to be added
to the MustBeKilled and MustBeUnused sets in ensure_opt_safe/6,
which means that it can only cause the optimization to be turned
off for code that used to be optimized.
|
|
The following code crashes beam_bool:
bad(XDo1, XDo2, Do3) ->
Do1 = (XDo1 =/= []),
Do2 = (XDo2 =/= []),
if Do1 =:= true;
Do1 =:= false, Do2 =:= false, Do3 =:= delete ->
no
end.
(Reported by Simon Cornish; minimized by Kostis Sagonas.)
For the moment fix the bug in the simplest and safest way possible
(basically, instead of crashing just don't do the optimization).
In a future major release (e.g. R14), the following improvements
could be considered:
* In beam_bool, it should be possible to move the Do1 and Do2
expressions to the pre-block and still optimize the expression
in the 'if' statement.
* In sys_core_fold, it should be possible to eliminate the
try/catch around the guard expression in the 'if', because
none of the guard tests can actually fail.
|