Age | Commit message (Collapse) | Author |
|
Code such as the following:
-record(x, {a}).
f(R, N0) ->
N = N0 / 100,
if element(1, R#x.a) =:= 0 ->
N
end.
would fail to compile with the following message:
m: function f/2+19:
Internal consistency check failed - please report this bug.
Instruction: {fmove,{fr,0},{x,1}}
Error: {uninitialized_reg,{fr,0}}:
This bug was introduced in 348b5e6bee2f.
Basically, the beam_type pass placed the fmove instruction in the
wrong place. Instructions that store to floating point registers and
instructions that read from floating point registers are supposed to
be in the same basic block.
Fix the problem by flushing all floating points instruction
before a call the pseudo-BIF is_record/3, thus making sure that
the fmove instruction is placed in the correct block.
Here is an annotated listing of the relevant part of the .S
file (before the fix):
{test_heap,{alloc,[{words,0},{floats,1}]},2}.
{fconv,{x,1},{fr,0}}.
{fmove,{float,100.0},{fr,1}}.
fclearerror.
{bif,fdiv,{f,0},[{fr,0},{fr,1}],{fr,0}}.
{fcheckerror,{f,0}}.
%% The instruction {fmove,{fr,0},{x,1}} should have
%% been here.
%% Block of instructions expanded from a call to
%% the pseudo-BIF is_record/3. (Expanded in a later
%% compiler pass.)
{test,is_tuple,{f,3},[{x,0}]}.
{test,test_arity,{f,3},[{x,0},2]}.
{get_tuple_element,{x,0},0,{x,2}}.
{test,is_eq_exact,{f,3},[{x,2},{atom,x}]}.
{move,{atom,true},{x,2}}.
{jump,{f,4}}.
{label,3}.
{move,{atom,false},{x,2}}.
{label,4}.
%% End of expansion.
%% The fmove instruction that beam_validator complains
%% about.
{fmove,{fr,0},{x,1}}.
Reported-by: Richard Carlsson
|
|
|
|
The beam_type may pass move and recalculates test_heap instructions.
The number of live registers are not always the lowest. Minimize the
number of registers by running beam_utils:live_opt/1 one more time.
|
|
|
|
Add math:floor/1 and math:ceil/1 to avoid unnecessary conversions
in floating point expressions. That is, instead of having to write
float(floor(X)) as part of a floating point expressions, we can
write simply math:floor(X).
|
|
The following code:
simple() ->
case try 0 after [] end of
0 -> college;
1 -> 0
end.
would crash the compiler like this:
crash reason: {case_clause,
{'EXIT',
{function_clause,
[{beam_type,simplify_select_val_int,
[{select,select_val,
{x,0},
{f,7},
[{integer,1},{f,9},{integer,0},{f,8}]},
0],
[{file,"beam_type.erl"},{line,169}]},
{beam_type,simplify_basic_1,3,
[{file,"beam_type.erl"},{line,155}]},
{beam_type,opt,3,[{file,"beam_type.erl"},{line,57}]},
{beam_type,function,1,[{file,"beam_type.erl"},{line,36}]},
{beam_type,'-module/2-lc$^0/1-0-',1,
[{file,"beam_type.erl"},{line,30}]},
{beam_type,module,2,[{file,"beam_type.erl"},{line,30}]},
{compile,'-select_passes/2-anonymous-2-',2,
[{file,"compile.erl"},{line,521}]},
{compile,'-internal_comp/4-anonymous-1-',2,
[{file,"compile.erl"},{line,306}]}]}}}
The root cause is that the type representation is not well-defined.
Integers could be represented in three different ways:
integer
{integer,{1,10}}
{integer,0}
However, only the first two forms were handled.
To avoid similar problems in the future:
* Make the type representation stricter. Make sure that integers are
only represented as 'integer' or {integer,{Min,Max}}.
* Call verify_type/1 whenever a new type is added (not only when
merging types) to ensure that only the supported types are added
to the type database).
(ERL-150)
|
|
We must be careful how we treat the type info for the result of:
setelement(Index, Tuple, NewValue)
If Tuple had type information, the result of setelement/3 (in x(0))
would be assigned the same type information. But that is not safe
for:
setelement(1, Tuple, NewValue)
since the type for the first element will be changed.
Therefore, we must take care to remove the type information for
the first element of the tuple if might have been modified by
setelement/3.
|
|
|
|
There is an optimization in beam_block to simplify a select_val
on a known boolean value. We can implement this optimization
in a cleaner way in beam_type and it will also be applicable
in more situations. (When I added the optimization to beam_type
without removing the optimization from beam_block, the optimization
was applied 66 times.)
|
|
The ASN.1 compiler often generates code similar to:
f(<<0:1,...>>) -> ...;
f(<<1:1,...>>) -> ....
Internally that will be rewritten to (conceptually):
f(<<B:1,Tail/binary>>) ->
case B of
0 ->
case Tail of ... end;
1 ->
case Tail of ... end;
_ ->
error(case_clause)
end.
Since B comes from a bit field of one bit, we know that the only
possible values are 0 and 1. Therefore the error clause can be
eliminated like this:
f(<<B:1,Tail/binary>>) ->
case B of
0 ->
case Tail of ... end;
_ ->
case Tail of ... end
end.
Similarly, we can also a deduce the range for an integer from
a 'band' operation with a literal integer.
While we are at it, also add a test case to improve the coverage.
|
|
The clause cannot possibly match, because there will always be
a {bif,...} clause that will match before reaching the fclearerror
instruction.
|
|
30cc5c90 changed the internal representation of catch and
try...catch, but beam_type was not updated in one place.
|
|
Put 'try' instructions inside block to improve the optimization
of allocation instructions. Currently, the compiler only looks
at initialization of y registers inside blocks when determining
which y registers that will be "naturally" initialized.
|
|
|
|
|
|
Profiling shows that the excution time for checkerror_1/2 could
be be near the top even for modules without any floating point
operations.
It turns out that the complexity of simplify_float_1/4 is quadratic.
checkerror/1 is called with the growing accumulator for each
iteration. checkerror/1 will traverse the entire accumulated list
*unless* some floating point operations are used.
We can avoid this situation if we only call checkerror/1 when there
are live floating point registers. We can also avoid calling flush/3
if there are no live floating point registers.
|
|
When calculating the number of live registers for allocation
instruction, it is not always safe to start with the number of live
registers at the start of the block. We will need to use the register
map to know whether there are any holes (dead registers) that are not
subsequently filled.
If the allocation instruction already has a number of live registers
calculated, there is nothing to be gained by raising it.
|
|
As a preparation for fixing a bug, introduce a complete register
map in the '%live' annotations.
|
|
|
|
|
|
|
|
The compiler shouldn't crash when fed an already-optimised BEAM assembly file.
|
|
files as delimiters.
While working on a tool that processes Erlang code and testing it against this repo,
I found out about those little sneaky 0xff. I thought it may be of help to other
people build such tools to remove non-conforming-to-standard characters.
|
|
|
|
In code such as:
X / 2
the following code would be output from beam_type for the division:
{fconv,{x,0},{fr,0}}.
{fconv,{integer,2},{fr,1}}.
fclearerror.
{bif,fdiv,{f,0},[{fr,0},{fr,1}],{fr,0}}.
That is, the integer 2 would be converted to the float 2.0 at
run-time by "{fconv,{integer,2},{fr,1}}". Make sure that we do
the conversion at compile time.
Noticed-by: Richard O'Keefe
|
|
|
|
|
|
|
|
Allow line/1 instructions to be part of a sequence of floating point
instructions to avoid outputting fclearerror / fcheckerror around
every floating point instruction.
|
|
|
|
The clause does not server any useful purpose, since it does the
same as the default clause at the end.
|
|
The following instruction sequence:
fmove {fr,Fr} {x,TempXreg}
move {x,TempXreg} {y,Dest}
is rewritten to:
fmove {fr,Fr} {y,Dest}
(Provided that {x,TempXreg} is killed by the instructions following
the sequence.)
Generalize the optimization to also handle:
fmove {fr,Fr} {x,TempXreg}
move {x,TempXreg} {_,Dest}
That is, the destination register can be either an X or Y register.
|
|
* bg/compiler-remove-r11-support:
compiler: Don't support the no_binaries option
erts: Don't support the put_string/3 instruction
compiler: Don't support the no_constant_pool option
compiler: Don't support the r11 option
test_server: Don't support communication with R11 nodes
binary_SUITE: Don't test bit-level binary roundtrips with R11 nodes
erts: Test compatibility of funs with R12 instead of R11
OTP-8531 bg/compiler-remove-r11-support
|
|
The no_constant_pool option was implied by the r11 option. It turns
off the usage of the constant (literal) pool, so that BEAM
instructions that use constants can be loaded in an R11 system.
Since the r11 option has been removed, there is no need to
retain the no_constant_pool option.
|
|
|